USART
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
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;
GPIO_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通讯协议
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通信
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 总线使用串行数据传输方式,且总线协议支持多主控制器。当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;
}
}