STM32F407 CAN发送注意事项

STM32使用的baseCAN,使用过程中发现一些注意的事项,特此记录。

现象:

  CAN发送程序,在1ms以上间隔调用时,一切正常。

  当连续调用CAN发送程序4次或更多时,表现为丢数据,仅能发送一条或2条CAN数据。

分析原因:

  1、STM32提供3个用于发送的mailbox。

  2、当间隔1ms或连续发送3条以内时,我的应用程序会按调用标准库函数,自动装载mailbox,表现为发送正常。

  3、当连续发送超过4条时,因为3个mailbox还没有发送完成,处于满的状态,因此应用程序会收到无空闲的应答同时清除未发送的mailbox,造成数据丢失。

修改程序:

  1、以3个mailbox满为标准,进行超时等待,结果发送数据不丢但顺序乱了。

  2、每装载一个mailbox都等待发送完成后,再装载下一个;等待最大时间限制为2ms(for循环5000次)。

 

小结:

  装载到mailbox的三个数据,不是按装载顺序发送的,而是按固定123的寄存器顺序发送的,只要mailbox1有数据,2、3就会等待发送,因此判断mailbox满的逻辑不可行。

  经测试正常情况下500kbps时,等待发送完成用时约300us(for循环800次),限时2ms足够。

转载于:https://www.cnblogs.com/aaron511/p/11422332.html

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的STM32F407CAN发送代码示例: ```c #include "stm32f4xx.h" void CAN_Configuration(void); int main(void) { CAN_Configuration(); while (1) { CAN1->sTxMailBox[0].TIR = 0x06500000; // 设置发送标识符为0x065 CAN1->sTxMailBox[0].TDLR = 0x01234567; // 设置发送数据 CAN1->sTxMailBox[0].TDTR = 0x08; // 设置发送数据长度为8位 CAN1->sTxMailBox[0].TIR |= 0x01; // 设置请求发送 while((CAN1->sTxMailBox[0].TIR & 0x01) != 0); // 等待发送完成 delay(1000); // 延时1秒后再次发送 } } void CAN_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; CAN_InitTypeDef CAN_InitStructure; /* 使能GPIO和CAN时钟 */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); /* 配置CAN引脚 */ GPIO_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_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* 配置CAN */ CAN_InitStructure.CAN_ABOM = DISABLE; CAN_InitStructure.CAN_AWUM = DISABLE; CAN_InitStructure.CAN_BS1 = CAN_BS1_9tq; CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq; CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; CAN_InitStructure.CAN_NART = DISABLE; CAN_InitStructure.CAN_Prescaler = 3; CAN_InitStructure.CAN_RFLM = DISABLE; CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; CAN_Init(CAN1, &CAN_InitStructure); /* 过滤器配置 */ CAN_FilterInitTypeDef CAN_FilterInitStructure; CAN_FilterInitStructure.CAN_FilterNumber = 0; CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000; CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000; CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; CAN_FilterInit(&CAN_FilterInitStructure); /* 启动CAN */ CAN_Cmd(CAN1, ENABLE); /* 等待CAN准备就绪 */ while(CAN_GetFlagStatus(CAN1, CAN_FLAG_INITOK) == RESET); /* 进入循环模式 */ CAN1->FMR |= 0x01; CAN1->FM1R &= 0x00; CAN1->FS1R |= 0x00; CAN1->FFA1R |= 0x00; CAN1->FA1R |= 0x01; } ``` 这个代码示例的作用是配置STM32F407的CAN1发送一帧数据,发送标识符为0x065,发送的数据为0x01234567。代码首先定义了CAN和GPIO的配置函数CAN_Configuration,并在主函数中调用该函数以进行配置。 在主循环中,代码首先配置CAN1发送邮箱的标识符和数据。然后设置请求发送位,等待发送完成。完成后通过delay函数延时1秒后再次发送。 配置函数CAN_Configuration首先使能了CAN和GPIO的时钟,然后配置了CAN引脚为复用功能,设置引脚速率为100MHz。接下来,使用CAN_Init函数配置CAN的参数,设置了波特率、模式等。 然后,代码配置了CAN的过滤器,用于过滤接收到的消息。最后,启动CAN并等待初始化完成。 请注意,在使用该代码之前,需要根据实际情况进行适当修改和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值