参考资料:

1、正点原子探索者STM32f407开发板-《STM32f407开发指南-库函数版本》-第32章 CAN 通讯实验;

2、STM32F4xx 官方参考资料《STM32F4xx中文参考手册》-第24章-控制器区域网络 (bxCAN)。

目录

CAN基础知识介绍

什么是CAN?

CAN协议的特点:

关于隐形电平和显性电平:

关于数据帧:

数据帧的构成:

总线仲裁:

位时序:

一个位的构成(示例):

位时序各段的作用和Tq数:

CAN控制器简介&工作模式-bxCAN

CAN控制器框图:

CAN标识符筛选器:

CAN 发送流程:

CAN 接收流程:

位时序:

CAN寄存器(部分):

CAN主控制寄存器(CAN_MCR)

CAN位时序寄存器(CAN_BTR)

CAN接收FIFO寄存器(CAN_RF0R/CAN_RF1R)

CAN发送邮箱标识符寄存器(CAN_TIxR)(x=0~2)

CAN发送邮箱数据寄存器(CAN_TDLxR/CAN_TDHxR) (x=0~2)(重要)

CAN接收FIFO邮箱邮箱数据寄存器(CAN_RDLxR/CAN_RDHxR) (x=0/1)(重要)

CAN筛选器组i寄存器x(CAN_FiRx)(i=0~27,x=1/2)

初始化流程:

CAN 初始化函数使用示例

初始化函数:

发送函数:

接收函数:

中断服务函数:

main函数:


CAN基础知识介绍

什么是CAN?

CAN是Controller Area Network 的缩写(以下称为CAN),是ISO国际标准化的串行通信协议。CAN协议经过ISO标准化后有两个标准:ISO11898标准和ISO11519-2标准。其中ISO11898是针对通信速率为125Kbps~1Mbps的高速通信标准,而ISO11519-2是针对通信速率为125Kbps以下的低速通信标准。

CAN协议的特点:

①多主控制。总线空闲时,所有单元都可发送消息,而两个以上的单元同时开始发送消息时,根据标识符(ID,非地址)决定优先级,并对各消息ID 的每个位进行逐个仲裁比较。仲裁获胜(优先级最高)的单元可继续发送消息仲裁失利的单元则立刻停止发送而进行接收工作。

②系统柔软性。连接总线的单元,没有类似“地址”的信息,因此,在总线上添加单元时,已连接的其他单元的软硬件和应用层都不需要做改变。

③速度快,距离远。最高1Mbps(距离<40M),最远可达10KM(速率<5Kbps)。

④具有错误检测、错误通知和错误恢复功能。所有单元都可以检测错误(错误检测功能),检测出错误的单元会立即同时通知其他所有单元(错误通知功能),正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新发送此消息直到成功发送为止(错误恢复功能)。

⑤故障封闭功能。CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。

⑥连接节点多。CAN 总线是可同时连接多个单元的总线。可连接的单元总数理论上是没有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。

正是因为CAN协议的这些特点,使得CAN特别适合工业过程监控设备的互连,因此,越来越受到工业界的重视,并已公认为最有前途的现场总线之一。

关于隐形电平和显性电平:

注意:CAN_L和CAN_H在隐形电平下任然不是0V,而是介于2~3V之间。

而最常用,最复杂的是数据帧。

关于数据帧:

数据帧由7个段组成:

①帧起始。

表示数据帧开始的段。

②仲裁段。

表示该帧优先级的段。

③控制段。

表示数据的字节数及保留位的段。

④数据段。

数据的内容,一帧可发送0~8个字节的数据。

⑤CRC段。

检查帧的传输错误的段。

⑥ACK段。

表示确认正常接收的段。

⑦帧结束。

表示数据帧结束的段。

数据帧的构成:

1、帧起始。标准帧和扩展帧都是由1个位的显性电平表示帧起始。

2、仲裁段。表示数据优先级的段,标准帧和扩展帧格式在本段有所区别。

其中标准段包含ID、RTR;拓展段包含ID、RTR、SRR、IDE。

ID:高位在前,低位在后。

基本ID,禁止高7位都为隐性,即不能:ID=1111111XXXX。

RTR:远程请求位。0,数据帧;1, 远程帧。

SRR:替代远程请求位。设置为1(隐性电平)。

IDE:标识符选择位。0,标准标识符;1,扩展标识符。

3、控制段。由6个位构成,表示数据段的字节数。标准帧和扩展帧的控制段稍有不同。

r0,r1:保留位。必须以显现电平发送,但是接收可以是隐性电平。

DLC:数据长度码。0~8,表示发送/接收的数据长度(字节)。

IDE:标识符选择位。0,标准标识符;1,扩展标识符;

4、数据段。该段可包含0~8个字节的数据,从最高位(MSB)开始输出。标准帧和扩展帧在这个段的格式完全一样:

5、CRC段。该段用于检查帧传输错误。由15个位的CRC顺序和1个位的CRC界定符(用于分隔的位)组成,标准帧和扩展帧在这个段的格式也是相同的:

CRC的值计算范围包括:帧起始、仲裁段、控制段、数据段。

接收方以同样的算法计算 CRC 值并进行比较,不一致时会通报错误。

6、ACK段。此段用来确认是否正常接收。由ACK槽(ACK Slot)和ACK界定符2个位组成。标准帧和扩展帧在这个段的格式也是相同的:

发送单元ACK段:发送2个隐性位。

接收单元ACK段:接收到正确消息的单元,在ACK槽发送显性位,通知发送单元,正常接收结束。称之为发送ACK/返回ACK。

注意:发送 ACK 的是既不处于总线关闭态也不处于休眠态的所有接收单元中,接收到正常消息的单元(发送单元不发送ACK)。正常消息是指:不含填充错误、格式错误、CRC 错误的消息。

7、帧结束。由7个位的隐性位组成。标准帧和扩展帧在这个段格式完全一样。

总线仲裁:

同时多个单元发送数据时候,总线仲裁过程:

1,总线空闲时,最先发送的单元获得发送优先权,一但发送,其他单元无法抢占。

2,如果有多个单元同时发送,则连续输出显性电平多的单元,具有较高优先级。

从ID开始比较,如果ID相同,还可能会比较RTR和SRR等位。

位时序:

位速率:由发送单元在 非同步的情况下发送的 每秒钟的位数称为位速率。一个位一般可以分为如下四段:
同步段( SS )
传播时间段( PTS )
相位缓冲段 1 ( PBS1 )
相位缓冲段 2 ( PBS2 )

这些段又由可称为 Time Quantum(时间段,以下称为Tq)的最小时间单位构成。

Tq就像构成物质的基本粒子一样,无数个原子组成了宏观意义上的物质。

字的组成结构:

Tq->段->位(bit)->字节(Byte)->半字(Half word)->字(Word)

也就是说,我们可以通过改变一个位包含的Tq多少来设定一个位传输的时间,也即改变传输时间,从而改变波特率的大小。

一个位的构成(示例):

1 位分为 4 个段,每个段又由若干个Tq 构成,这称为位时序。

传输一个位(bit)数据所需要的时间就叫:位时间。

位时间=1/波特率,因此,知道位时间,我们就可以知道波特率。

1 位由多少个Tq 构成、每个段又由多少个Tq 构成等,可以任意设定位时序。通过设定位时序,多个单元可同时采样,也可任意设定采样点。

位时序各段的作用和Tq数:

CAN控制器简介&工作模式-bxCAN

STM32自带了基本扩展CAN外设,又称bxCAN,bxCAN的特点如下:
支持CAN协议2.0A和2.0B主动模式
波特率最高达1Mbps
支持时间触发通信
具有3个发送邮箱
具有3级深度的2个接收FIFO

可变的筛选器组(也称过滤器组,最多28个)

工作模式: 通过CAN_MCR寄存器控制INRQ和SLEEP
①初始化模式(INRQ=1,SLEEP=0)
正常模式(INRQ=0,SLEEP=0)

③睡眠模式(SLEEP=1)

测速模式:通过CAN_BTR寄存器控制LBKM和SILM

①静默模式( LBKM=0,SILM=1 )

此时,只接收CANRX上的数据,CANTX上的数据一直是1(隐形电平);且内部可形成环路,自发自收

可用于监控总线数据。

环回模式( LBKM=1,SILM=0 )

与静默模式相反,只发送,不接受;且内部可形成环路,自发自收

可用于测试输出信号。

③环回静默模式(LBKM=1,SILM=1)

与总线均断开。

CAN控制器框图:

F1只有一个主CAN,F407有两个CAN,此图为双CAN框架图。

两个CAN分别拥有自己的发送邮箱和接收FIFO,但是他们共用28个过滤器(筛选器)。

接收 FIFO:

硬件使用两个接收 FIFO 来存储传入消息,分别是FIFO 0FIFO 1。每个 FIFO 中可以存储三条完整消息。FIFO 完全由硬件管理。

CAN标识符筛选器:

STM32F4 的过滤器(也称筛选器)组最多有 28 个,每个滤波器组 x 由 2 个 32 为寄存器, CAN_FxR1 和 CAN_FxR2 组成(x=0~27)。

①、 CAN的标识符不表示目的地址而是 表示发送优先级接收节点根据标识符的值,来决定是否接收对应消息。
②、STM32F4 CAN控制器,提供了28个可配置的筛选器组(F1仅互联型才有28个,其他的只有14个),可降低CPU处理CAN通信的开销。
③、STM32F4 CAN控制器每个筛选器组由2个32位寄存器组成(CAN_FxR1和CAN_FxR2,x=0~27)。根据位宽不同,每个筛选器组可提供:

● 1个32位筛选器,包括:STDID[10:0]、EXTID[17:0]、IDE和RTR位

● 2个16位筛选器,包括:STDID[10:0]、IDE、RTR和EXTID[17:15]位

④、筛选器可配置为: 屏蔽位模式标识符列表模式在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按照“ 必须匹配”或“ 不用关心”处理。 而在标识符列表模式下,屏蔽寄存器也被 当作标识符寄存器用
举个例子,我们设置过滤器组 0 工作在:1 个 32 位过滤器- 标识符屏蔽模式,然后 设置 CAN_F0R1=0XFFFF0000,CAN_F0R2=0XFF00FF00。其中存放到 CAN_F0R1 的值就是 期望收到的 ID,即我们希望收到的 ID(STID+EXTID+IDE+RTR)最好是:0XFFFF0000。而 0XFF00FF00 就是设置我们 需要必须关心的 ID,表示收到的 ID,其位[31:24]和位[15:8]这 16 个 位的必须和 CAN_F0R1 中对应的位一模一样,而另外的 16 个位则不关心,可以一样,也可以 不一样,都认为是正确的 ID,即收到的 ID 必须是 0XFFxx00xx,才算是正确的(x 表示不关心)。
因此,不是采用一个标识符加一个屏蔽位的方式,而是使用2个标识符寄存器。接收报文标识符的每一位都必须跟筛选器标识符相同。

为了过滤出一组标识符,应该设置过滤器组工作在屏蔽位模式

为了过滤出一个标识符,应该设置过滤器组工作在标识符列表模式

通过CAN_FM1RCAN_FS1R可配置筛选器的位宽和模式:

关于标识符过滤的详细介绍,请参考《STM32F4xx 中文参考手册》的 24.7.4 节。

CAN 发送流程:

CAN正常发送流程为:

开始:程序选择1个空置的邮箱(TME=1)

-> 设置标识符(ID),数据长度和发送数据

-> 设置CAN_TIxR的TXRQ位为1,请求发送

-> 邮箱挂号(等待成为最高优先级)

-> 预定发送(等待总线空闲)

-> 发送

-> 邮箱空置

CAN 接收流程:

CAN正常接收流程为:

开始:FIFO

-> 收到有效报文

-> 挂号_1(存入FIFO的一个邮箱,这个由硬件控制,我们不需要理会)

-> 收到有效报文

-> 挂号_2

-> 收到有效报文

-> 挂号_3

-> 收到有效报文

-> 溢出

CAN收到的有效报文,存储在3级邮箱深度的FIFO中。FIFO接收到的报文数,我们可以通过查询CAN_RFxR的FMP寄存器来得到,只要FMP不为0,我们就可以从FIFO读出收到的报文。

注:报文FIFO具有锁定功能(由CAN_MCR,RFLM位控制),锁定后,新数据将丢弃,不锁定则新数据将替代老数据。

位时序:

注1:STM32的CAN将传播时间段相位缓冲时间段1合并成时间段1。

注2:tPCLK=1/fPCLK,F103中的fPCLK=36Mhz,F407中的fPCLK=42Mhz。

例如:

STM32F103,设TS1=8、TS2=7、BRP=3,波特率=36,000,000/[(9+8+1)*4]=500,000bps。

STM32F407,设TS1=6、TS2=5、BRP=5,波特率=42,000,000/[(7+6+1)*6]=500,000bps。

CAN寄存器(部分):

CAN主控制寄存器(CAN_MCR)

此寄存器仅介绍下INRQ位,该位用来控制初始化请求。

设置INRQ=0,可使CAN从初始化模式进入正常工作模式

设置INRQ=1,可使CAN从正常工作模式进入初始化模式

CAN初始化时,先设置INRQ=1 ,进入初始化模式,进行初始化(尤其是CAN_BTR的设置,该寄存器,必须在CAN正常工作之前设置),之后再设置INRQ=0,进入正常工作模式。

CAN位时序寄存器(CAN_BTR)

CAN接收FIFO寄存器(CAN_RF0R/CAN_RF1R)

CAN_RF0R用于FIFO0控制

CAN_RF1R用于FIFO1控制

CAN发送邮箱标识符寄存器(CAN_TIxR)(x=0~2)

CAN发送邮箱数据寄存器(CAN_TDLxR/CAN_TDHxR) (x=0~2)(重要)

图为CAN_TDLxR寄存器的描述,用于存储低4个字节的数据。CAN_TDHxR寄存器与之类似,用于存储高4个字节的数据。要发送的数据就是存储在这两个寄存器。 

CAN接收FIFO邮箱邮箱数据寄存器(CAN_RDLxR/CAN_RDHxR) (x=0/1)(重要)

图为CAN_RDLxR寄存器的描述,用于存储低4个字节的数据。CAN_RDHxR寄存器与之类似,用于存储高4个字节的数据。接收到的数据就存储在这两个寄存器。

CAN筛选器组i寄存器x(CAN_FiRx)(i=0~27,x=1/2)

注:STM32F103ZET6只有0~13

每个筛选器组的CAN_FiRx都由2个32位寄存器构成,即:CAN_FiR1CAN_FiR2。根据过滤器位宽和模式的不同设置,这两个寄存器的功能也不尽相同。

初始化流程:

①配置相关引脚的复用功能,使能CAN时钟。

要用CAN,先要使能CAN的时钟,CAN的时钟通过APB1ENR的第25位来设置。其次要设置CAN的相关引脚为复用输出,这里我们需要设置PA11为上拉输入(CAN_RX引脚)PA12为复用输出(CAN_TX引脚),并使能PA口的时钟

②设置CAN工作模式及波特率等。

通过先设置CAN_MCR寄存器的INRQ位,让CAN进入初始化模式,然后设置CAN_MCR的其他相关控制位。再通过CAN_BTR设置波特率和工作模式(正常模式/环回模式)等信息。 最后设置INRQ为0,退出初始化模式。

③设置滤波器。

本例程,我们将使用筛选器组0,并工作在32位标识符屏蔽位模式下。先设置CAN_FMR的FINIT位,进入初始化模式,然后设置筛选器组0的工作模式以及标识符ID和屏蔽位。最后激活筛选器,并退出初始化模式。

CAN 初始化函数使用示例

初始化函数:

CAN初始化函数名: u8 CAN 1 _Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{GPIO_InitTypeDef       GPIO_InitStructure; CAN_InitTypeDef        CAN_InitStructure;CAN_FilterInitTypeDef  CAN_FilterInitStructure;
#if CAN1_RX0_INT_ENABLE NVIC_InitTypeDef       NVIC_InitStructure;
#endif//使能相关时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能PORTA时钟                                                               RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟 //初始化GPIOGPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA11,PA12//引脚复用映射配置GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); //GPIOA11复用为CAN1GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1); //GPIOA12复用为CAN1//CAN单元设置CAN_InitStructure.CAN_TTCM=DISABLE;  //非时间触发通信模式   CAN_InitStructure.CAN_ABOM=DISABLE;  //软件自动离线管理    CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的  CAN_InitStructure.CAN_TXFP=DISABLE;    //优先级由报文标识符决定 CAN_InitStructure.CAN_Mode= mode;     //模式设置 CAN_InitStructure.CAN_SJW=tsjw;    //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tqCAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tqCAN_InitStructure.CAN_BS2=tbs2;//Tbs2范围CAN_BS2_1tq ~    CAN_BS2_8tqCAN_InitStructure.CAN_Prescaler=brp;  //分频系数(Fdiv)为brp+1   CAN_Init(CAN1, &CAN_InitStructure);   // 初始化CAN1 //配置过滤器CAN_FilterInitStructure.CAN_FilterNumber=0;      //过滤器0CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位IDCAN_FilterInitStructure.CAN_FilterIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASKCAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化#if CAN1_RX0_INT_ENABLECAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.          NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     // 主优先级为1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
#endifreturn 0;
}  

发送函数:

//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)
//len:数据长度(最大为8)
//msg:数据指针,最大为8个字节.
//返回值:0,成功;
//其他,失败;
u8 Can_Send_Msg(u8* msg,u8 len)
{   u8 mbox;u16 i=0;CanTxMsg TxMessage;TxMessage.StdId=0x12;      // 标准标识符 TxMessage.ExtId=0x12;     // 设置扩展标示符 TxMessage.IDE=CAN_Id_Standard;  // 标准帧TxMessage.RTR=CAN_RTR_Data;      // 数据帧TxMessage.DLC=len;           // 要发送的数据长度for(i=0;i<len;i++)TxMessage.Data[i]=msg[i]; mbox= CAN_Transmit(CAN1, &TxMessage);   i=0;while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;//等待发送结束if(i>=0XFFF)return 1;return 0;
}

接收函数:

//can口接收数据查询
//buf:数据缓存区;
//返回值:0,无数据被收到;
//其他,接收的数据长度;
u8 Can_Receive_Msg(u8 *buf)
{                  u32 i;CanRxMsg RxMessage;if( CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0;   //没有接收到数据,直接退出 CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);    //读取数据  for(i=0;i<8;i++)buf[i]=RxMessage.Data[i];  return RxMessage.DLC;
}

中断服务函数:

如果R0中断开启了的话

#if CAN1_RX0_INT_ENABLE  //使能RX0中断
//中断服务函数
void CAN1_RX0_IRQHandler(void)
{CanRxMsg RxMessage;int i=0;CAN_Receive(CAN1, 0, &RxMessage);for(i=0;i<8;i++)printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data[i]);
}
#endif

main函数:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "key.h"
#include "can.h"int main(void)
{ u8 key;u8 i=0,t=0;u8 cnt=0;u8 canbuf[8];u8 res;u8 mode=1;//CAN工作模式;0,普通模式;1,环回模式NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2delay_init(168);    //初始化延时函数uart_init(115200);  //初始化串口波特率为115200LED_Init();                    //初始化LED LCD_Init();                    //LCD初始化 KEY_Init();                //按键初始化  CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack);//CAN初始化环回模式,波特率500Kbps    POINT_COLOR=RED;//设置字体为红色 LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");    LCD_ShowString(30,70,200,16,16,"CAN TEST");   LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(30,110,200,16,16,"2014/5/7");LCD_ShowString(30,130,200,16,16,"LoopBack Mode");     LCD_ShowString(30,150,200,16,16,"KEY0:Send WK_UP:Mode");//显示提示信息     POINT_COLOR=BLUE;//设置字体为蓝色    LCD_ShowString(30,170,200,16,16,"Count:");         //显示当前计数值   LCD_ShowString(30,190,200,16,16,"Send Data:");        //提示发送的数据   LCD_ShowString(30,250,200,16,16,"Receive Data:"); //提示接收到的数据      while(1){key=KEY_Scan(0);if(key==KEY0_PRES)//KEY0按下,发送一次数据{for(i=0;i<8;i++){canbuf[i]=cnt+i;//填充发送缓冲区if(i<4)LCD_ShowxNum(30+i*32,210,canbuf[i],3,16,0X80);     //显示数据else LCD_ShowxNum(30+(i-4)*32,230,canbuf[i],3,16,0X80);    //显示数据}res=CAN1_Send_Msg(canbuf,8);//发送8个字节 if(res)LCD_ShowString(30+80,190,200,16,16,"Failed");        //提示发送失败else LCD_ShowString(30+80,190,200,16,16,"OK    ");           //提示发送成功                                   }else if(key==WKUP_PRES)//WK_UP按下,改变CAN的工作模式{      mode=!mode;CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,mode);  //CAN普通模式初始化,普通模式,波特率500KbpsPOINT_COLOR=RED;//设置字体为红色 if(mode==0)//普通模式,需要2个开发板{LCD_ShowString(30,130,200,16,16,"Nnormal Mode ");       }else //回环模式,一个开发板就可以测试了.{LCD_ShowString(30,130,200,16,16,"LoopBack Mode");}POINT_COLOR=BLUE;//设置字体为蓝色 }      key=CAN1_Receive_Msg(canbuf);if(key)//接收到有数据{         LCD_Fill(30,270,160,310,WHITE);//清除之前的显示for(i=0;i<key;i++){                                       if(i<4)LCD_ShowxNum(30+i*32,270,canbuf[i],3,16,0X80);   //显示数据else LCD_ShowxNum(30+(i-4)*32,290,canbuf[i],3,16,0X80);  //显示数据}}t++; delay_ms(10);if(t==20){LED0=!LED0;//提示系统正在运行  t=0;cnt++;LCD_ShowxNum(30+48,170,cnt,3,16,0X80);    //显示数据}        } }

Fin

STM32F4-CAN通讯相关推荐

  1. 示波器观察IIC通讯协议-STM32F4读写24C08EEPROM时序图-新人首更

    示波器观察时序不是因为好奇,是因为遇到了问题 STM32F4探索者开发板板载24C02EEPROM,自制了一块开发板,需要存储容量更大的24C08A芯片,焊接后发现开发板上能成功运行的程序,在自己的板 ...

  2. 工程文件参考——CubeMX+STM32F4+FreeRTOS+IIC实现JY901通讯

    文章目录 代码实现 JY901.h JY901.c # 前言 本文主要提供F4系列芯片针对JY901芯片的通讯库,供各位参考 JY901芯片提供的库函数是没有F4芯片的资料的,我对着提供的F1芯片模拟 ...

  3. STM32F4+LAN8720A+STM32CubeMX+Lwip 网络通讯(以太网通讯)小实例

    一.目标实现      通过网络通信的方式,当上位机发出对应指令给STM32,STM32根据收到的指令来执行对应的操作(例如:亮灯.灭灯.闪灯等).还有可以将STM32连上路由器,当电脑连上路由器后, ...

  4. STM32F4 HAL库开发 -- 串口

    一.串口介绍 串口设置包含:开启串口时钟.设置响应的IO口模式.设置波特率.数据位长度.奇偶校验位.DMA等信息. 具体参看:STM32开发 – 串口详解 二.函数 1.串口参数初始化,并使能串口. ...

  5. STM32F4+Wi-Fi+EDP 向 OneNet 上传数据

    源地址:https://www.arduino.cn/thread-19000-1-1.html     利用STM32F4+WIFI+EDP向OneNet平台上传数据,虽然非常简单,但是在个人调试过 ...

  6. 基于STM32F4的智能门锁系统

    基于STM32F4的智能门锁系统 前言 一.项目背景 二.项目所预想功能 三.外置硬件准备 四.项目开发 简介及涉及协议 蓝牙模块 1.蓝牙接线图 2.使用说明: 3.蓝牙代码 USART3.C 蓝牙 ...

  7. STM32环境下AS5048A14位磁旋转编码器SPI通讯调试记录——我学到的东西、遇到的问题、解决的过程

    ❤ 2019.3.16 事情是这样的. 在很多天以前,老师接了个项目,问我有没有意向,我谨慎的表达了我对新事物的好奇心,对新知识的求知欲,同时又委婉的表达了我的能力有限的实际情况,然后我以为事情就这么 ...

  8. 工业通讯 | STM32F4xx应用控制器与SoM集成 Ⅱ

    上期回顾:工业通讯 | STM32F4xx应用控制器与SoM集成 STM32F4xx应用控制器与SoM集成 目录 1 介绍 2 准备工作 2.1 硬件要求 2.2 STM32F429I-Nucleo ...

  9. 基于STM32F4单片机对步进电机的控制(有代码)

    步进电机简介 步进电机是将电脉冲控制信号转变为角位移或线位移的一种常用的数字控制执行元件,又称为脉冲电机.在驱动电源的作用下,步进电机受到脉冲的控制,其转子的角位移量和速度严格地与输入脉冲的数量和脉冲 ...

  10. STM32F4主板硬件设计与接口

    更多交流欢迎关注作者抖音号:81849645041 本专栏的所有程序都在飞航科技 STM32-F407 开发板上测试通过,本文介绍一下STM32-F407 开发板硬件设计与接口,便于读者学习交流. S ...

最新文章

  1. 密码学研究-数字签名
  2. 查看oralce的版本及安装了哪些选项
  3. 这几天有django和python做了一个多用户博客系统(可选择模板) 没完成,先分享下...
  4. 阿联酋起源人工智能研究院(IIAI)诚邀优秀人才加盟
  5. TS Type As
  6. 使用 Xshell 连接矩池云 GPU服务器
  7. idea工具修改Git路径
  8. C++奥赛一本通排序题解
  9. Hibernate-逆向工程
  10. java-类库-Apache Commons
  11. 惊艳!用 Python 送女神们别样的礼物!
  12. 最全CTF Web题思路总结(更新ing)
  13. 大三,在软件工程学习上的感悟
  14. 随机抽取一名同学回答问题,7/4更新一次
  15. 使用PLC-Recorder快速连接PLC记录数据
  16. 理解LaaS、SaaS、PaaS的含义及区别
  17. 排位赛中 服务器崩溃修复后连不上,lol手游出现creating a lobby问题怎么办?服务器崩溃解决方法说明[多图]...
  18. 树莓派(4B)DHT11实现温湿度获取+mysql数据库存储
  19. 个人信息保护建设实践方法的探索过程
  20. Born近似和Rytov近似

热门文章

  1. BZOJ3759: Hungergame 博弈论+线性基
  2. 基于Unity3D开发hololens应用-环境配置
  3. 小米4x性能服务器图片介绍,红米4x怎么样 红米4X性能参数评测【详解】
  4. 使用VBA将大纲级别定义良好的单个Word文档按指定的大纲样式分割成多个文档
  5. 【100%通过率】华为OD机试真题 Java 实现【分奖金】【2022.11 Q4 新题】
  6. 内涵社 weixin.php,GitHub - yzbx/weixin: This is an enclosed class for WeChat apis. 微信公共平台api的php封装...
  7. Photoshop CC2015软件安装教程
  8. 11-标准库fmt以及文件操作
  9. 2022年第十三届蓝桥杯Java B组第三题:字符统计
  10. 玩游戏哪款蓝牙耳机好?2021十大高音质游戏蓝牙耳机排名