目录

  • 1 博客内容
  • 2 STM32芯片、TJA1050、上位机
  • 3 CAN环回模式、轮询/中断接收模式
  • 4 程序原理
  • 5 主程序(Main.c)
  • 6 CAN程序(CAN.c)
  • 7 CAN头文件(CAN.h)
  • 8 程序测试
  • 9 总结

1 博客内容

博客内容基于STM32F103 RET6芯片(Keil.STM32F1xx_DFP.2.3.0.pack)+PCA82C250,使用CAN通讯环回模式测试CAN收发。CAN引脚对应PA11(RX)和PA12(TX),使用PB11电压测试数据是否成功。实际测试中PB11输出正常,但PA11和PA12异常,接示波器排查判断PCA82C250硬件故障。

2 STM32芯片、TJA1050、上位机

STM32芯片引脚电平为3.3V,而CAN逻辑电压为0和2.5V。因此STM32芯片和CAN解析器(eg:周立功_USBCAN/Vector_CANape)之间需要收发器,将TTL电平转CAN逻辑电压。本文使用的收发器为PCA82C250,其中TJA1050和PCA82C250可以相互替换。

3 CAN环回模式、轮询/中断接收模式

CAN环回模式用于CAN测试,对外发送同时自己接收。

      CAN接收理解两种模式:

  • 轮询接收模式。不论收件箱是否有邮件,都在不停收,直到收到为止。博客内容参考STM32官方帮助文件。文件位置:D:\Soft\Keil\Demo\en.stsw-stm32054\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\CAN\LoopBack。

  • 中断接收模式。CAN接收FIFO(( First Input First Output))寄存器CAN_RF0R,到有消息到达,该寄存器的0和1位会累加(硬件执行),显示消息挂起。通过该位判断是否接收。

    中断模式查看挂起消息数量(官方自带库函数):

uint8_t CAN_MessagePending(CAN_TypeDef* CANx, uint8_t FIFONumber)
{uint8_t message_pending=0;/* Check the parameters */assert_param(IS_CAN_ALL_PERIPH(CANx));assert_param(IS_CAN_FIFO(FIFONumber));if (FIFONumber == CAN_FIFO0){message_pending = (uint8_t)(CANx->RF0R&(uint32_t)0x03);}else if (FIFONumber == CAN_FIFO1){message_pending = (uint8_t)(CANx->RF1R&(uint32_t)0x03);}else{message_pending = 0;}return message_pending;
}

4 程序原理

CAN对外发送(TX)标准ID为0x11的数据帧,长度为2个字节(内容为0xCA,0xFE)。对接收(RX)内容进行判断,如果全部正确,PB11高电平(实际该引脚连接接示波器,未连接LED)。

  if (RxMessage.StdId!=0x11){return 0;  }if (RxMessage.IDE!=CAN_ID_STD){return 0;}if (RxMessage.DLC!=2){return 0;  }if ((RxMessage.Data[0]<<8|RxMessage.Data[1])!=0xCAFE){return 0;}

5 主程序(Main.c)

//================================================
//    名称:  Main.c
//    作者:  Morven_X
//    版本:  1.1
//    编制:  2021/03/5 23:55
//    更新:  2021/03/08 20:37
//    功能:  基于STM32F103 RET6芯片,使用CAN发送和接收信息
//    简介:  使用回环模式查看CAN发送,使用USBCAN接收数据(失败)
//    Email:  morven_xie@163.com
//================================================# include "stm32f10x.h"
# include "stm32f10x_gpio.h"
# include "stm32f10x_can.h"
# include "Delay.h"
# include "CAN.h" int main(void)
{LED_Init();LED_PB_Init();Delay_Init();CAN_GPIO_Init();NVIC_Configuration();        JTAG_Init();/* Turns selected LED Off */  LED_Off_PB11;LED_Off_PB12;LED_Off_PB13;LED_Off_PB14;int i;int TestRx;while (1) {/* CAN transmit at 125Kb/s and receive by polling in loopback mode */TestRx = CAN1_Polling();if (TestRx == 0){/* Faild to turn on led PB13 */LED_On_PB13;}else{/*Success to turn on PB11 */LED_On_PB11;}/*PC3-LED_ON */    LED_On;Delay_ms(100);//  while(i < 0xFFFFF)
//  {//    i++;
//  }LED_Off_PB11;LED_Off_PB12;LED_Off;//   while(i >0x01)
//  {//    i--;
//  }   Delay_ms(100);}
}

6 CAN程序(CAN.c)

# include "stm32f10x_rcc.h"
# include "stm32f10x_gpio.h"
# include "CAN.h"void LED_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);  //使能C口GPIO时钟GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;     //选择推挽输出GPIO_InitStruct.GPIO_Pin=GPIO_Pin_3 | GPIO_Pin_6;                     //指定引脚3GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;        //设置输出速率50MHz//GPIO_Init(GPIOC,&GPIO_InitStruct);                           //初始化外设GPIOx寄存器
}void LED_PB_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  //使能B口GPIO时钟GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;     //选择推挽输出GPIO_InitStruct.GPIO_Pin=GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;       //指定引脚GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;     //设置输出速率50MHz//GPIO_Init(GPIOB,&GPIO_InitStruct);                           //初始化外设GPIOx寄存器
}void CAN_GPIO_Init(void)
{//**********GPIO初始化**********//GPIO_InitTypeDef        GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  //使能A口GPIO时钟GPIO_InitStruct.GPIO_Pin=GPIO_Pin_11 ;                 //指定引脚PA11,CAN_RX上拉输入GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;        //设置输出速率50MHz//GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;        //选择上拉输入GPIO_Init(GPIOA,&GPIO_InitStruct);                          //初始化外设GPIOA寄存器GPIO_InitStruct.GPIO_Pin=GPIO_Pin_12 ;                //指定引脚PA12,CAN_TX复用推挽GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;        //设置输出速率50MHz//GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;     //选择推挽输出    GPIO_Init(GPIOA,&GPIO_InitStruct);                          //初始化外设GPIOA寄存器
}/*** @brief  Configures the NVIC and Vector Table base address.* @param  None* @retval None*/
void NVIC_Configuration(void)
{NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}void JTAG_Init(void)
{   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);    //先开启开启AFIO复用时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);   //使能GPIOA外设时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);   //使能GPIOB外设时钟GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//关闭JTAG,保留SWD(若同时关闭SWD,芯片作废)
}int CAN1_Polling(void)
{   CAN_InitTypeDef        CAN_InitStructure;CAN_FilterInitTypeDef  CAN_FilterInitStructure;CanTxMsg TxMessage;CanRxMsg RxMessage;uint32_t i = 0;uint8_t TransmitMailbox = 0;/* CAN register init */CAN_DeInit(CAN1);CAN_StructInit(&CAN_InitStructure);RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);/* CAN cell init */CAN_InitStructure.CAN_TTCM=DISABLE;CAN_InitStructure.CAN_ABOM=DISABLE;CAN_InitStructure.CAN_AWUM=DISABLE;CAN_InitStructure.CAN_NART=DISABLE;CAN_InitStructure.CAN_RFLM=DISABLE;CAN_InitStructure.CAN_TXFP=DISABLE;CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;/* Baudrate = 125kbps*/CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;CAN_InitStructure.CAN_BS1=CAN_BS1_2tq;CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;CAN_InitStructure.CAN_Prescaler=48;CAN_Init(CAN1, &CAN_InitStructure);/* CAN filter init */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=0;CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;CAN_FilterInit(&CAN_FilterInitStructure);/* transmit */TxMessage.StdId=0x11;TxMessage.RTR=CAN_RTR_DATA;TxMessage.IDE=CAN_ID_STD;TxMessage.DLC=2;TxMessage.Data[0]=0xCA;TxMessage.Data[1]=0xFE;TransmitMailbox=CAN_Transmit(CAN1, &TxMessage);i = 0;while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && (i != 0xFFFF)){i++;}i = 0;while((CAN_MessagePending(CAN1, CAN_FIFO0) < 1) && (i != 0xFFFF)){i++;}/* receive */RxMessage.StdId=0x00;RxMessage.IDE=CAN_ID_STD;RxMessage.DLC=0;RxMessage.Data[0]=0x00;RxMessage.Data[1]=0x00;CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);if (RxMessage.StdId!=0x11){return 0;  }if (RxMessage.IDE!=CAN_ID_STD){return 0;}if (RxMessage.DLC!=2){return 0;  }if ((RxMessage.Data[0]<<8|RxMessage.Data[1])!=0xCAFE){return 0;}return 1; /* Test Passed */
}

7 CAN头文件(CAN.h)

#ifndef  _CAN_H
#define  _CAN_Hvoid LED_Init(void);
void LED_PB_Init(void);
void NVIC_Configuration(void);
void CAN_GPIO_Init(void);
void JTAG_Init(void);
int CAN1_Polling(void);#define LED_On       GPIO_SetBits(GPIOC,GPIO_Pin_3) ;
#define LED_On_PB11  GPIO_SetBits(GPIOB,GPIO_Pin_11) ;
#define LED_On_PB12  GPIO_SetBits(GPIOB,GPIO_Pin_12) ;
#define LED_On_PB13  GPIO_SetBits(GPIOB,GPIO_Pin_13) ;
#define LED_On_PB14  GPIO_SetBits(GPIOB,GPIO_Pin_14) ;#define LED_Off_PB11 GPIO_ResetBits(GPIOB,GPIO_Pin_11) ;
#define LED_Off_PB12 GPIO_ResetBits(GPIOB,GPIO_Pin_12) ;
#define LED_Off_PB13 GPIO_ResetBits(GPIOB,GPIO_Pin_13) ;
#define LED_Off_PB14 GPIO_ResetBits(GPIOB,GPIO_Pin_14) ;
#define LED_Off      GPIO_ResetBits(GPIOC,GPIO_Pin_3) ;#endif

8 程序测试

PB11和接地,与示波器连接:

      示波器显示结果_Delay(100ms):

      示波器显示结果_(i=0,i < 0xFFFFF,i++):

      增加82C250,其与电源连接。引脚连接RX和TX、CANH和CANL。检查4个电压:

      CAN收发器通过DB9接头接入USBCAN出现异常,连接示意:

      CANtest数据异常展示,基于以上判断转换器故障。

9 总结

通过B站 刘洋:基础篇 19 STM32 CAN总线通讯实验
视频学习和STM32官方帮助文件学习(官方帮助文件ST STM32F10x_StdPeriph_Lib_V3.5.0),重码官方的STM32芯片的回环模式程序,了解CAN主控制函数(CAN_MCR)、唤醒方式、波特率等相关IO口和寄存器设置。虽然最终未能结合DBC查看数据,但实现初始目标。
      至此,嵌入式基础开发告一段落。

>> 更多相关内容,点击Morven_Xie博客概览

STM32嵌入式基础开发附C-STM32-CAN通讯相关推荐

  1. 应邀ITGeGe在线教育社区嵌入式基础开发讲师

    最近,被一家IT在线公司邀请去做嵌入式基础课程的讲师,我感觉非常荣幸,虽然我还是菜鸟一个,难得有这样的企业会看得起我,这也是对我的一个磨练吧,可以培养我继续不断学习技术的动力,同时还能将技术通过自身的 ...

  2. 【嵌入式设计开发】基于STM32 HD01双H桥高功率C车模车驱动板 程序设计

    HD01高功率驱动高速小车 HD01双H桥高功率赛车驱动板 驱动参数 引脚分配 引脚性能 STM32驱动代码 初始化代码 电机控制代码 控制频率参数 HD01双H桥高功率赛车驱动板 HD01高功率驱动 ...

  3. stm32 python界面开发_【STM32开发】使用Qt Creator 开发STM32

    在之前的文章中我们介绍了如何使用VSCode去构建一个STM32的单片机项目,今天我们来说一下使用 Qt Creator 来开发STM32单片机. 0x01: 开发环境准备 PlatformIO Co ...

  4. Linux嵌入式驱动开发零基础入门集合(STM32过渡到Linux嵌入式)

    Linux嵌入式驱动开发01--第一个驱动Hello World(附源码) Linux嵌入式驱动开发02--驱动编译到内核 Linux嵌入式驱动开发03--杂项设备驱动(附源码) Linux嵌入式驱动 ...

  5. 从新建工程开始使用C++开发单片机(以STM32为例):六、C++输入输出流(附代码)

    经过前面几篇文章的铺垫,完成了C语言接口层的GPIO.外部中断.串口.delay等接口,现在可以正式进入C++驱动层的文章.当然C语言接口层的还远没有完成,在以后的文章中还会继续更新. 本文将会介绍一 ...

  6. 基于stm32的linux开发的书籍,跟工程师学嵌入式开发:基于STM32和μC OS-Ⅲ 带目录高清版pdf...

    本书选用的STM32芯片基于ARM Cortex-M3体系结构,根据基于MCU的嵌入式技术实际应用需求,合理地选择了多种常用的重要外设接口,如USART.SPI.I2C.FSCM.SDIO总线.以太网 ...

  7. 什么是嵌入式AI开发?人工智能芯片指什么?STM32、树莓派、Jetson TX2、华为昇腾部署神经网络区别在哪?

    嵌入式芯片:https://zhuanlan.zhihu.com/p/449570075 芯片公司代表:https://www.jiqizhixin.com/articles/2020-01-31-9 ...

  8. 学完stm32开发板下一步如何选嵌入式ARM开发板

    如何选择ARM开发板 市场上开发板玲琅满目,我们怎么来选择ARM开发板呢?除了要求ARM开发板资料齐全以外,技术是不是主流.能否结合当前嵌入式产品的应用开发需要,也是很关键的,因为IT技术发展很快,不 ...

  9. STM32与树莓派:嵌入式系统开发与教育计算的区别

    STM32和树莓派是两种不同的硬件平台,用于不同的应用领域. STM32:STM32是一系列由STMicroelectronics(意法半导体)生产的32位ARM Cortex-M微控制器.它们被广泛 ...

最新文章

  1. iOS10 权限崩溃问题
  2. Android 关于获取摄像头帧数据解码
  3. 近期发现的一些-20190519
  4. 双层lstm每层有自己的权重参数吗_一幅图真正理解LSTM的物理结构
  5. springboot aop使用_Spring Boot 的自动配置,是如何实现的?
  6. CentOS 7 Root用户密码重置 2017-04-02
  7. 自定义列表字段类型(3)
  8. java正则表达式验证密码_java密码验证正则表达式校验
  9. C语言stdio相关的几个函数
  10. Linux 源代码 安装vsftpd 2.3.4
  11. Cocos Creator实战教程(5)】——打砖块(物理引擎,碰撞检测)
  12. DOM基本操作(二:对节点的操作)
  13. 超微服务器电源短接启动图解_教你一招,让你的电脑启动速度秒杀别人
  14. springboot entity date_「Java」 - SpringBoot amp; JPA多数据源
  15. 欢迎访问我的博客园,希望对你有所帮助
  16. 勤哲服务器项目模板,勤哲excel服务器,模板.doc
  17. 通过adb命令查看SN、CID码等信息
  18. Android 仿支付宝搜索结果页,字符串部分文字显示高亮
  19. opencv - viz 画出SLAM轨迹
  20. 每月分享之兰迪·波许教授的最后一课

热门文章

  1. 面向对象:13、内部类
  2. ROOT后安装Magisk,使用Magisk Hide 解决建设银行APP-一元流量不能用问题
  3. 便利店里的常用日语:“找”的日语不都是「探す」
  4. 【TencentOS tiny】 超详细的TencentOS tiny移植到STM32F103全教程
  5. 为什么你需要RS485转LoRaWAN的数据采集器?
  6. U盘数据丢失误删全攻略
  7. Centos7 Cannot find a valid baseurl for repo: base/7/x86_64
  8. Linux文本编辑命令
  9. 久坐导致臀部肌肉抑制无力,6个孤立动作全面提高臀部肌肉力量
  10. C语言期末复习划重点啦!赶上复习的末班车,祝你期末考试不挂科!