USART该接口是一种高度灵活的串行通信设备,具有以下特点:
1. 全双工操作(独立接收和发送数据);
2. 同步操作时,或从机时钟同步;
3. 不占用定时/计数器的独立高精度波特率发生器;
4. 串行数据帧结构支持5、6、7、8、9位数据位,1或2位停止位;
5. 由硬件支持的奇偶校验位发生和检验;
6. 数据溢出检测;
7. 帧错误检测;
8. 检测噪声滤波器和数字低通滤波器包括错误的起始位置;
9. 三个完全独立的中断,TX发送完成、TX发送数据寄存器空,RX接收完成;
10.支持多机通信模式;
11.支持倍速异步通信模式。
传输协议:
stm32常用代码
USART结构体的初始化 typedef struct { uint32_t USART_BaudRate; // 波特率 uint16_t USART_WordLength; // 字长 uint16_t USART_StopBits; // 停止位 uint16_t USART_Parity; // 校验位 uint16_t USART_Mode; // USART 模式 uint16_t USART_HardwareFlowControl; // 硬件流控制 } USART_InitTypeDef;
void USART_Init(u32 bound) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1和GPIOA时钟 USART_DeInit(USART1); ///复位串口1(各参数为缺省值) //USART1_TX(发送数据) PA.9引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA.9 //USART1_RX(接收数据) PA.10引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;///浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA.10 //NVIC中断向量配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;///抢占优先级为3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级为3,优先级取决于不同中断的重要性。 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); ///根据上述设置的参数初始化NVIC寄存器 //USART初始化设置 USART_InitStructure.USART_BaudRate = bound;//波特率9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据 USART_InitStructure.USART_StopBits = USART_StopBits_1;//1停止位 USART_InitStructure.USART_Parity = USART_Parity_No;///无奇偶校准位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;///无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //串口初始化 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//中断开启 USART_Cmd(USART1, ENABLE); ///串口使能 }
/***************** 发送一个字符 **********************/ void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch) { /* 发送字节数据到 USART */ USART_SendData(pUSARTx,ch); /* 等待发送的数据寄存器是空的 */ while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } /***************** 发送字符串 **********************/ void Usart_SendString( USART_TypeDef * pUSARTx, char *str) { unsigned int k=0; do { Usart_SendByte( pUSARTx, *(str k) ); k ; } while (*(str k)!='\0'); /* 等待发送完成 */ while (USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) { } }
void DEBUG_USART_IRQHandler(void) { uint8_t ucTemp; if (USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET) { ucTemp = USART_ReceiveData( DEBUG_USARTx ); USART_SendData(USARTx,ucTemp); } }
int main(void) { /*初始化 USART 配置模式为 115200 8-N-1,中断接收*/ USART_Init(); Usart_SendString( DEBUG_USARTx,"这是一个串口中断接收显示实验\n"); while (1) { } }
I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 由于引脚少,公司开发的硬件很实用 现在简单,可扩展性强,不需要 USART、CAN 外部收发设备等通信协议,现在被广泛使用 系统中使用多个集成电路(IC)间的通讯。 IIC协议可分为物理层和协议层。
I2C串行总线一般有两条信号线,一条是双向数据线SDA,另一个是时钟线SCL。所有接到I2C总线设备上的串行数据SDA都接到总线SDA上,每台设备的时钟线SCL接到总线的SCL上。
通信格式:
stm32常用代码
void I2C1_GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GIO_InitStructure.GPIO_OType = GPIO_OType_OD;//必须设置为开漏输出,实现iic的线与逻辑
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_I2C1);
}
void I2C1_Configuration(void)
{
I2C_InitTypeDef I2C_InitStructure;
I2C_DeInit(I2C1);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0XA0;//主机的地址
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress= I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000;//100KHZ
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
}
void I2C1_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
I2C1_GPIO_Configuration();
I2C1_Configuration();
}
写数据
uint8_t I2C_Master_BufferWrite(I2C_TypeDef * I2Cx, uint8_t* pBuffer, uint32_t NumByteToWrite, uint8_t SlaveAddress)
{
if(NumByteToWrite==0)
return 1;
/* 1.开始*/
I2C_GenerateSTART(I2Cx, ENABLE);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
/* 2.设备地址·/写 */
I2C_Send7bitAddress(I2Cx, SlaveAddress, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
/* 3.连续写数据 */
while(NumByteToWrite--)
{
I2C_SendData(I2Cx, *pBuffer);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
pBuffer++;
}
/* 4.停止 */
I2C_GenerateSTOP(I2Cx, ENABLE);
while ((I2Cx->CR1&0x200) == 0x200);
return 0;
}
读数据
uint8_t I2C_Master_BufferRead(I2C_TypeDef * I2Cx, uint8_t* pBuffer, uint32_t NumByteToRead, uint8_t SlaveAddress)
{
if(NumByteToRead==0)
return 1;
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
I2C_AcknowledgeConfig(I2Cx, ENABLE);
/* 1.开始*/
I2C_GenerateSTART(I2Cx, ENABLE);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
/* 2.设备地址·/写 */
I2C_Send7bitAddress(I2Cx, SlaveAddress, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
/* 3.开始*/
I2C_GenerateSTART(I2Cx, ENABLE);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
/* 4.设备地址·/读 */
I2C_Send7bitAddress(I2Cx, SlaveAddress, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
/* 5.连续写数据 */
while (NumByteToRead)
{
if(NumByteToRead==1)
{
I2C_AcknowledgeConfig(I2Cx, DISABLE);
I2C_GenerateSTOP(I2Cx, ENABLE);//6.停止,非应答
}
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* EV7 */
*pBuffer++ = I2C_ReceiveData(I2Cx);
NumByteToRead--;
}
I2C_AcknowledgeConfig(I2Cx, ENABLE);
return 0;
}
RS-232是美国电子工业协会EIA(ElectronicIndustry Association)制定的一种串行物理接口标准。RS是英文“推荐标准”的缩写,232为标识号通常。RS-232 接口以9个引脚 (DB-9) 或是25个引脚(DB-25) 的型态出现,一般个人计算机上会有两组RS-232 接口,分别称为 COM1 和 COM2 。
RS-232总线规定了25条线,包含了两个信号通道,即第一通道(称为主通道)和第二通道(称为副通道)。利用RS- 232总线可以实现全双工通信,通常使用的是主通道,而副通道使用较少。在一般应用中,使用3条~9条信号线就可以实现全双工通信,采用三条信号线(接收线、发送线和信号线)能实现简单的全双工通信过程。
RS-232规定的标准传送速率有50b/s、75b/s、110b/s、150b/s、300b/s、600b/s、1200b/s、2400b/s、4800b/s、9600b/s、19200b/s,可以灵活地适应不同速率的设备。对于慢速外设,可以选择较低的传送速率:反之,可以选择较高的传送速率。
采用负逻辑传送
规定逻辑“1”的电平为-5V~-15 V,逻辑“0”的电平为+5 V~+15 V。选用该电气标准的目的在于提高抗干扰能力,增大通信距离。RS -232的噪声容限为2V,接收器将能识别高至+3V的信号作为逻辑“0”,将低到-3 V的信号作为逻辑“1”。
传送距离较远
由于RS -232采用串行传送方式,并且将微机的TTL电平转换为RS-232C电平,其传送距离一般可达30 m。若采用光电隔离20 mA的电流环进行传送,其传送距离可以达到1000 m。另外,如果在RS-232总线接口再加上Modem,通过有线、无线或光纤进行传送,其传输距离可以更远。
RS232C标准接口有25根线,常用的只有9根,它们是:
(1)接收线信号检出( Received Line Signal Detection,RSD)——用来表示DCE已接通通信链路,告知DTE准备接收数据。此线也叫作数据载波检出(Data Carrier detection,DCD)线。
(2)接收数据( Received data,RXD)——通过RXD线终端接收从 MODEM发来的串行数据(DCE→DTE)。
(3)发送数据( Transmitted data,TXD)——通过TXD终端将串行数据发送到 MODEM(DTE→DCE)。
(4)数据终端准备好( Data Terminal Ready,DTR)——有效时(ON)状态,表明数据终端可以使用。
(5)地线-GND。
(6)数据装置准备好( Data Set ready,DSR)——有效时(ON)状态,表明通信装置处于可以使用的状态。
(7)请求发送( Request to Send)——用来表示DTE请求DCE发送数据,即当终端要发送数据时,使该信号有效(ON状态),向 MODEM请求发送。它用来控制 MODEM是否要进入发送状态。 [3]
(8)清除发送( Clear to Send,CTS)―用来表示DCE准备好接收DTE发来的数据,是对请求发送信号RTS的响应信号。当 MODEM已准备好接收终端传来的数据并向前发送时,使该信号有效,通知终端开始沿发送数据线TXD发送数据。
(9)振铃指示( Ringing,R)——当 MODEM收到交换台送来的振铃呼叫信号时,使该信号有效(ON状态),通知终端,已被呼叫。
SPI,是一的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。
SPI接口一般使用四条信号线通信: SDI(数据输入),SDO(数据输出),SCK(时钟),CS(片选)
MISO: 该引脚在从模式下发送数据,在主模式下接收数据。 MOSI: 该引脚在主模式下发送数据,在从模式下接收数据。 SCLK:串行时钟信号,由主设备产生。 CS/SS:从设备片选信号,由主设备控制避免数据线上的冲突。
SPI通信有4种不同的操作模式,不同的从设备可能在出厂是就是配置为某种模式,这是不能改变的;但我们的通信双方必须是工作在同一模式下,所以我们可以对我们的主设备的SPI模式进行配置,通过CPOL(时钟极性)和CPHA(时钟相位)来 控制我们主设备的通信模式,具体如下:
时钟极性(CPOL)定义了时钟空闲状态电平:
CPOL=0,表示当SCLK=0时处于空闲态,所以有效状态就是SCLK处于高电平时 CPOL=1,表示当SCLK=1时处于空闲态,所以有效状态就是SCLK处于低电平时
时钟相位(CPHA)定义数据的采集时间。
CPHA=0,在时钟的第一个跳变沿(上升沿或下降沿)进行数据采样,在第2个边沿发送数据 CPHA=1,在时钟的第二个跳变沿(上升沿或下降沿)进行数据采样,在第1个边沿发送数据
stm32常用程序
typedef struct
{
uint16_t SPI_Direction; /*!< 传输方向,两向全双工,单向接收等*/
uint16_t SPI_Mode; /*!< 模式选择,确定主机还是从机 */
uint16_t SPI_DataSize; /*!< 数据大小,8位还是16位 */
uint16_t SPI_CPOL; /*!< 时钟极性选择 */
uint16_t SPI_CPHA; /*!< 时钟相位选择 */
uint16_t SPI_NSS; /*!< 片选是硬件还是软件*/
uint16_t SPI_BaudRatePrescaler; /*!< 分频系数 */
uint16_t SPI_FirstBit; /*!< 指定数据传输是从MSB还是LSB位开始的。M
SB就是二进制第一位,LSB就是最后一位 */
uint16_t SPI_CRCPolynomial; /*!< CRC校验 ,设置 CRC 校验多项式,提高通
信可靠性,大于 1 即可*/
}SPI_InitTypeDef;
void SPI2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI2时钟使能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //PB13/14/15上拉
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_Cmd(SPI2, ENABLE); //使能SPI外设
SPI2_ReadWriteByte(0xff);//启动传输
}
标准库:
u8 SPIx_ReadWriteByte(u8 TxData)
{
u8 retry=0;
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
{
}//等待发送区空
SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个byte 数据
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
{
} //等待接收完一个byte
return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据
}
HLA库:
uint8_t SPI_SendByte(uint8_t byte)
{
uint8_t d_read,d_send=byte;
if(HAL_SPI_TransmitReceive(&hspi1,&d_send,&d_read,1,0xFFFFFF)!=HAL_OK)
d_read=0XFF;
return d_read;
CAN 总线使用串行数据传输方式,且总线协议支持多主控制器。当CAN 总线上的一个节点(站)发送数据时,它以报文形式广播给网络中所有节点。
每组报文开头的11位字符为标识符,定义了报文的优先级,这种报文格式称为面向内容的编址方案。在同一系统中标识符是唯一的,不可能有两个站发送具有相同标识符的报文。当几个站同时竞争总线读取时,这种配置十分重要。
CAN总线使用双绞线进行差分电压传输,两条信号线被称为CAN高(CAN_H)和CAN_L)。
两条线静态时均为2.5V左右,此时状态表示为逻辑1,也被称作隐性。当两条线电压值出现差异时,通常CAN_H=3.5V和CAN_L=1.5V,此时状态表示为逻辑0,也称作显性。即:
差分电压CAN_diff = 0V,表示逻辑“1”,为隐性
差分电压CAN_diff = 2V,表示逻辑“0”,为显性
#include "pbdata.h"
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void CAN_Configuration(void);
int main(void)
{
CanTxMsg TxMessage;
RCC_Configuration(); //时钟配置
GPIO_Configuration();//端口配置
NVIC_Configuration();
CAN_Configuration();
while(1)
{
//每隔1s发送一个报文,一个报文8B
TxMessage.StdId=0xFF00>>5;//标准帧只有31-21位,对于16位寄存器而言,低五位为扩展帧,所以在写16位数据时,最后5位置0
TxMessage.ExtId=0;
TxMessage.IDE=CAN_ID_STD;//选择发送标准帧
//TxMessage.StdId=0;
//TxMessage.ExtId=0xFFFFFFFF>>3;//扩展帧只有18位,在32位数据时最后三位为(IDE,RTR,TXRQ),所以在写扩展帧时,最后三位要置0
//TxMessage.IDE=CAN_ID_EXT;
//发送扩展帧
TxMessage.RTR=CAN_RTR_DATA;//发送的是数据帧
//TxMessage.RTR=CAN_RTR_REMOTE;//远程帧,只发送ID,不发送数据,将ID发给另一台设备,请求另一台设备返回数据
TxMessage.DLC=8;//数据长度8B
TxMessage.Data[0]=0x11;
TxMessage.Data[1]=0x22;
TxMessage.Data[2]=0x33;
TxMessage.Data[3]=0x44;
TxMessage.Data[4]=0x55;
TxMessage.Data[5]=0x66;
TxMessage.Data[6]=0x77;
TxMessage.Data[7]=0x88;
//数据内容
can_tx_success_flag = 0;
CAN_Transmit(CAN1,&tx_message);//can发送数据
while(can_tx_success_flag == 0);//是否一次发送成功
delay_ms(1000);//1s一次
}
}
void RCC_Configuration(void)
{
SystemInit();//72m
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//端口重映射
GPIO_PinRemapConfig(GPIO_Remap1_CAN1,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;//RX
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void CAN_Configuration(void)
{
//硬件上有个can/usb才能与PC通讯
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_DeInit(CAN1);
CAN_StructInit(&CAN_InitStructure);
//关闭时间触发模式
CAN_InitStructure.CAN_TTCM=DISABLE;
//关闭自动离线管理
CAN_InitStructure.CAN_ABOM=DISABLE;
//关闭自动唤醒模式
CAN_InitStructure.CAN_AWUM=DISABLE;
//禁止报文自动重传
CAN_InitStructure.CAN_NART=DISABLE;
//FIFO溢出时报文覆盖源文件
CAN_InitStructure.CAN_RFLM=DISABLE;
//报文发送优先级取决于ID号,本次只用了一个发送邮箱,关闭TXFP
CAN_InitStructure.CAN_TXFP=DISABLE;
//工作模式(正常)
CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;
//波特率设置125 KBPS
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1=CAN_BS1_3tq;
CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;
CAN_InitStructure.CAN_Prescaler = 48;
//初始化CAN
CAN_Init(CAN1,&CAN_InitStructure);
//屏蔽滤波(can接收才涉及)
CAN_FilterInitStructure.CAN_FilterNumber=0;//0号滤波器
//屏蔽滤波模式
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//标识符屏蔽位模式
//32位寄存器
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
//标识符寄存器高16位
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0F00;
//标识符寄存器低16位
CAN_FilterInitStructure.CAN_FilterIdLow=0;
//屏蔽寄存器高16位
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0F00;
//屏蔽寄存器低16位
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0;
//过滤器将ID报文关联到FIFO0缓存区中,数据只能从这里导出
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;
//过滤器使能
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
//初始化过滤器
CAN_FilterInit(&CAN_FilterInitStructure);
//接收中断使能
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);
//发送中断使能
CAN_ITConfig(CAN1,CAN_IT_TME,ENABLE);
}
void USB_LP_CAN1_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
CanTxMsg TxMessage;
//CAN接收
CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);//can接收的数据存在FIFO0的RxMessage里
TxMessage.StdId=RxMessage.StdId;//标准ID
TxMessage.ExtId=RxMessage.ExtId;//扩展ID
TxMessage.IDE=RxMessage.IDE;//标准帧还是扩展帧
TxMessage.RTR=RxMessage.RTR;//数据帧还是远程帧
TxMessage.DLC=RxMessage.DLC;//待传输数据长度
TxMessage.Data[0]=RxMessage.Data[0];
TxMessage.Data[1]=RxMessage.Data[1];
TxMessage.Data[2]=RxMessage.Data[2];
TxMessage.Data[3]=RxMessage.Data[3];
TxMessage.Data[4]=RxMessage.Data[4];
TxMessage.Data[5]=RxMessage.Data[5];
TxMessage.Data[6]=RxMessage.Data[6];
TxMessage.Data[7]=RxMessage.Data[7];
//CAN发送
CAN_Transmit(CAN1,&TxMessage);
}
//进发送中断的目的是为了设置can发送成功标志位
void USB_HP_CAN1_TX_IRQHandler(void) //CAN TX
{
if (CAN_GetITStatus(CAN1,CAN_IT_TME)!= RESET)
{
CAN_ClearITPendingBit(CAN1,CAN_IT_TME);
can_tx_success_flag=1;
}
}