你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F207下的实验(1)- CAN通信基础

[复制链接]
STMCU小助手 发布时间:2021-12-4 20:04
CAN控制器通过两根线上的电位差来判断总线电平

can.h
  1. #can.h

  2. #include"stm32f2xx.h"

  3. #ifndef __CAN_H_
  4. #define __CAN_H_

  5. void CAN_Mode_Config(u8 CAN_BS1_xtq, u8 CAN_BS2_ytq, u16 Prescaler);

  6. u8 CAN_Send_Msg(u8 *msg, u8 len);

  7. u8 CAN_Receive_Msg(u8 *buf);

  8. #endif
复制代码

can.c
  1. #include"stm32f2xx.h"
  2. #include"stm32f2xx_can.h"
  3. #include"can.h"

  4. void CAN_Mode_Config(u8 CAN_BS1_xtq, u8 CAN_BS2_ytq, u16 Prescaler)
  5. {
  6.         GPIO_InitTypeDef  GPIO_InitStructure;
  7.         CAN_InitTypeDef CAN_InitStructure;
  8.         CAN_FilterInitTypeDef CAN_FilterInitStructure;
  9.         NVIC_InitTypeDef NVIC_InitStructure;

  10.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);  //使能AHB1外设时钟
  11.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);  //使能CAN1时钟

  12.         //GPIO初始化
  13.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
  14.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  15.     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  16.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  17.     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  18.     GPIO_Init(GPIOD, &GPIO_InitStructure);

  19.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1);
  20.         GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1);
  21.         

  22.         //CAN初始化
  23.         CAN_InitStructure.CAN_ABOM = DISABLE;           //软件自动离线管理        
  24.         CAN_InitStructure.CAN_AWUM = DISABLE;   //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
  25.         CAN_InitStructure.CAN_BS1 = CAN_BS1_xtq;   //时间段1的时间单元,取值在CAN_BS1_1tq~CAN_BS1_16tq
  26.         CAN_InitStructure.CAN_BS2 = CAN_BS2_ytq;    //时间段2的时间单元,取值在CAN_BS2_1tq~CAN_BS2_8tq
  27.         CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;    //模式设置,普通模式
  28.         CAN_InitStructure.CAN_NART = ENABLE;      //禁止报文自动传送
  29.         CAN_InitStructure.CAN_Prescaler = Prescaler;         //分频系数(Fdiv)为brp+1        
  30.         CAN_InitStructure.CAN_RFLM = DISABLE;      //报文不锁定,新的覆盖旧的  
  31.         CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;    //重新同步跳跃时间单元,CAN_SJW_1tq~CAN_SJW_4tq
  32.         CAN_InitStructure.CAN_TTCM = DISABLE;    //非时间触发通信模式
  33.         CAN_InitStructure.CAN_TXFP = DISABLE;     //优先级由报文标识符决定
  34.         CAN_Init(CAN1, &CAN_InitStructure);

  35.         //筛选初始化
  36.         CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;    激活过滤器0
  37.         CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FilterFIFO0;    //过滤器0关联到FIFO0
  38.         CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;    //32位ID
  39.         CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
  40.         CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;   //32位MASK
  41.         CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
  42.         CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;    //屏蔽模式
  43.         CAN_FilterInitStructure.CAN_FilterNumber = 0;    //过滤器0
  44.         CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;    //
  45.         CAN_FilterInit(&CAN_FilterInitStructure);        

  46.         CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);   //fifo0的中断
  47.         NVIC_InitStructure.NVIC_IRQChannel = CAN1_TX_IRQn;  //stm..xx.h,发送中断
  48.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  49.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
  50.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
  51.         NVIC_Init(&NVIC_InitStructure);
  52. }

  53. //开始发送
  54. u8 CAN_Send_Msg(u8 *msg, u8 len)     //msg为数据,len为长度
  55. {
  56.         u8 mbox;   //邮箱
  57.         u16 i = 0;
  58.         
  59.         CanTxMsg TXmessage;    //can发送结构体
  60.                
  61.         TXmessage.DLC = len;  //数据个数,不能超过8个
  62.         TXmessage.ExtId = 0x12;    //扩展标示符
  63.         TXmessage.IDE = CAN_ID_STD;     //帧类型是标准帧,与这里的标准标示符和扩展标示符无关
  64.         //TXmessage.IDE = CAN_ID_EXT;   //这里的帧类型也可以设置为扩展帧,在USB_CAN那里设置标准帧,传输记录中会有
  65.         TXmessage.RTR = CAN_RTR_DATA;   //...can.h,传送的是数据帧
  66.         TXmessage.StdId = 0x12;  //标准标示符
  67.                
  68.         for(i = 0; i < len; i++)
  69.         {
  70.                 TXmessage.Data<i> = msg;
  71.         </i>}
  72.         
  73.         mbox = CAN_Transmit(CAN1, &TXmessage);  //返回当前邮箱

  74.         while((CAN_TransmitStatus(CAN1, mbox) == CAN_TxStatus_Failed)&&(i < 0xFFF))
  75.         {
  76.                 i++;      //等待发送结束完成
  77.         }
  78.         if(i >= 0xFFF)
  79.         {
  80.                 return 1;  
  81.         }        
  82.         return 0;
  83. }



  84. u8 CAN_Receive_Msg(u8 *buf)
  85. {
  86.         CanRxMsg RXmessage;         //can接收结构体
  87.         u16 i = 0;

  88.         while(CAN_MessagePending(CAN1, CAN_FIFO0) == 0)     //查询接收状态位,看是否由信息(报文)到达
  89.         {
  90.                 return 0;           //没有接收到数据,直接退出,看CAN_FIFO0中是否有数据
  91.         }
  92.         CAN_Receive(CAN1, CAN_FIFO0, &RXmessage);   //接收信息(报文),将CAN_FIFO0中的数据通过can1拷贝到RXmessage结构体中
  93.         
  94.         for(i = 0; i < RXmessage.DLC; i++)
  95.         {
  96.                 buf<span style="font-style: italic;"><span style="font-style: normal;"> = RXmessage.Data</span><span style="font-style: normal;">;
  97.         }

  98.         return RXmessage.DLC;
  99. }</span></span>
复制代码

led.h
  1. #include"stm32f2xx.h"

  2. #ifndef __LED_H

  3. #define __LED_H


  4. void LED_Init(void);

  5. void Delay(vu32 nCount);

  6. void CTL_LED(u8 LED_NUM, u8 OFF_ON);

  7.         
  8. #endif
复制代码

led.c
  1. #include"led.h"
  2. #include"stm32f2xx.h"

  3. void LED_Init(void)
  4. {
  5.         GPIO_InitTypeDef GPIO_InitStructure;
  6.         
  7.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
  8.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11;
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;   //led灯做输出,不用复用
  10.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //GPIO_OType_PP表示推挽方式输出,GPIO_OType_OD表示开漏
  11.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  12.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  13.         GPIO_Init(GPIOD, &GPIO_InitStructure);
  14.         GPIO_SetBits(GPIOD, GPIO_Pin_12|GPIO_Pin_11);
  15. }


  16. void Delay(vu32 nCount)
  17. {
  18.   for(; nCount != 0; nCount--);
  19. }

  20. #if 1
  21. void CTL_LED(u8 LED_NUM, u8 OFF_ON)
  22. {
  23.   switch(LED_NUM)
  24.         {
  25.             case 0:
  26.                         if(OFF_ON == 1)
  27.                         {

  28.                                 GPIO_ResetBits(GPIOD, GPIO_Pin_11);
  29.                         }
  30.                         else
  31.                         {
  32.                                 GPIO_SetBits(GPIOD, GPIO_Pin_11);
  33.                         }
  34.                     break;
  35.                     
  36.                 case 1:
  37.                         if(OFF_ON == 1)
  38.                         {

  39.                                 GPIO_ResetBits(GPIOD, GPIO_Pin_12);
  40.                         }
  41.                         else
  42.                         {
  43.                                 GPIO_SetBits(GPIOD, GPIO_Pin_12);
  44.                         }
  45.                     break;
  46.                 default:
  47.                         //GPIO_ResetBits(GPIOF,GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10);
  48.                         GPIO_SetBits(GPIOD,GPIO_Pin_11|GPIO_Pin_12);
  49.                     break;
  50.         }
  51. }
  52. #endif
复制代码

main.c

  1. #include"stm32f2xx.h"
  2. #include"can.h"
  3. #include"led.h"


  4. int main(void)
  5. {
  6.         u8 res;
  7.         u8 key;
  8.         
  9.         u8 canbuf[8] = {0};    //这里因为不知道从USB_CAN发的是什么,只需初始化为0即可
  10.         u8 a[8] = {02, 02, 02, 02, 02, 02, 02, 02};   //这里的02和2一样,12是0c

  11.         LED_Init();
  12.         Delay(168);

  13.         CAN_Mode_Config(CAN_BS1_8tq, CAN_BS2_6tq, 8);   //此时CAN波特率为:30000/(1+8+6)*8 = 250kbps

  14.         while(1)
  15.          {        
  16.             //1.接收数据
  17.             key = CAN_Receive_Msg(canbuf);

  18.                 //2.解析数据
  19.                 if(key == 0)
  20.                 {
  21.                         CTL_LED(1, 0);   //开始的时候,没有接收到数据,故左边灯亮
  22.                 }
  23.                 else if(key > 0)     //当接收到数据时,开始执行这一步
  24.                 {
  25.                     //3.发送数据给PC
  26.                     CTL_LED(1, 1);   
  27.                         res = CAN_Send_Msg(a, 8);   
  28.                         if(res == 0)
  29.                         {
  30.                                 CTL_LED(0, 1);   //若数据发送成功,点亮led灯0
  31.                         }
  32.                         else
  33.                         {
  34.                                 CTL_LED(1, 0);     //若数据发送失败,熄灭led灯1
  35.                                  
  36.                         }
  37.                 }        
  38.         }

  39. //开始的时候,没有接收到数据,故左边灯亮,当接收到数据时,开始执行发送数据函数,若发送成功,右边灯亮,
  40. //若数据发送失败,熄灭led灯1
  41. //问题:数据发送成功和失败的判断:是否合理?左边的灯会一直亮
  42. //结合上面程序,将没有接收到数据时灯灭,数据发送时灯亮,可知数据发送成功,
  43. //问题:can程序实验代码不显示接收?而且和发送数据框的数据无关?
  44. /*
  45.         while(1)
  46.         {
  47.                 res = CAN_Send_Msg(a, 8);
  48.                 if(res == 0)
  49.                 {
  50.                         CTL_LED(0, 1);   //若数据发送成功,点亮led灯0,即右边灯
  51.                         key = CAN_Receive_Msg(canbuf);
  52.                         if(key == 0)
  53.                         {
  54.                                 CTL_LED(1, 1);   //实验结果是,执行这一步
  55.                         }
  56.                         else if(key > 0)
  57.                         {
  58.                                 Delay(5000);
  59.                                 //CTL_LED(1, 1);   //灯1为左边的灯
  60.                         }
  61.                 }
  62.                 else
  63.                 {
  64.                         Delay(5000);
  65.                         //CTL_LED(1, 0);     //若数据发送失败,点亮led灯1
  66.                 }
  67.         }
  68. */        
  69. }

复制代码

收藏 评论0 发布时间:2021-12-4 20:04

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版