找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2832|回复: 0
打印 上一主题 下一主题
收起左侧

STM32 CAN通讯实现(发射机与接收机测试源程序)

[复制链接]
跳转到指定楼层
楼主
ID:332685 发表于 2018-5-18 08:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32 CAN通讯实现源码分享给大家

接收机单片机源程序如下:
  1. /**************************************************************************************
  2.                 作者:蓝想电子
  3.                 功能介绍:发射机作用每一S钟变量data自动加1,加到255又重0开始,循环发射。
  4.                           接收机收到数据,在串口上显示.
  5.                 注意:接收机的ID号必须跟发射机发射的ID号一致。
  6. ****************************************************************************************/                        

  7. #include "stm32f10x.h"
  8. #include <stdio.h>
  9. #include "delay.h"
  10. #include "can.h"
  11. extern u32 canid;
  12. extern u8 ReceiveData;
  13. //使用printf要在target里将 Use Micro LIB选中  必须加头文件stdio.h
  14. int fputc(int ch,FILE *f)
  15. {
  16.           USART_SendData(USART1, (u8) ch);
  17.       while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  18.           return ch;
  19. }

  20. /*************************************************
  21. 函数: void RCC_Configuration(void)
  22. 功能: 复位和时钟控制 配置
  23. 参数: 无
  24. 返回: 无
  25. **************************************************/
  26. void RCC_Configuration(void)
  27. {
  28.   ErrorStatus HSEStartUpStatus;                    //定义外部高速晶体启动状态枚举变量
  29.   RCC_DeInit();                                    //复位RCC外部设备寄存器到默认值
  30.   RCC_HSEConfig(RCC_HSE_ON);                       //打开外部高速晶振
  31.   HSEStartUpStatus = RCC_WaitForHSEStartUp();      //等待外部高速时钟准备好
  32.   if(HSEStartUpStatus == SUCCESS)                  //外部高速时钟已经准别好
  33.   {
  34.     FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //开启FLASH预读缓冲功能,加速FLASH的读取。所有程序中必须的用法.位置:RCC初始化子函数里面,时钟起振之后
  35.     FLASH_SetLatency(FLASH_Latency_2);                    //flash操作的延时
  36.               
  37.     RCC_HCLKConfig(RCC_SYSCLK_Div1);               //配置AHB(HCLK)时钟等于==SYSCLK
  38.     RCC_PCLK2Config(RCC_HCLK_Div1);                //配置APB2(PCLK2)钟==AHB时钟
  39.     RCC_PCLK1Config(RCC_HCLK_Div2);                //配置APB1(PCLK1)钟==AHB1/2时钟
  40.          
  41.     RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  //配置PLL时钟 == 外部高速晶体时钟 * 9 = 72MHz
  42.     RCC_PLLCmd(ENABLE);                                   //使能PLL时钟
  43.    
  44.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)    //等待PLL时钟就绪
  45.     {
  46.     }
  47.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);            //配置系统时钟 = PLL时钟
  48.     while(RCC_GetSYSCLKSource() != 0x08)                  //检查PLL时钟是否作为系统时钟
  49.     {
  50.     }
  51.   }

  52. }

  53. /*******************************************************************************
  54. * Function Name   : NVIC_Configuration
  55. * Description        : Configures NVIC and Vector Table base location.
  56. * Input                    : None
  57. * Output                 : None
  58. * Return                 : None
  59. *******************************************************************************/
  60. void NVIC_Configuration(void)
  61. {
  62.    NVIC_InitTypeDef NVIC_InitStructure;
  63.   
  64.    /* Set the Vector Table base location at 0x08000000 */
  65.    NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
  66.   
  67.    /* Configure the NVIC Preemption Priority Bits */  
  68.    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  69.   
  70.    /* Enable the USART1 Interrupt */
  71.    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;       //通道设置为串口1中断
  72.    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;           //中断响应优先级0
  73.    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                   //打开中断
  74.    NVIC_Init(&NVIC_InitStructure);                                                    //初始化
  75. }

  76. /*******************************************************************************
  77.         函数名:USART1_Configuration
  78.         输  入:
  79.         输  出:
  80.         功能说明:
  81.         初始化串口硬件设备,启用中断
  82.         配置步骤:
  83.         (1)打开GPIO和USART1的时钟
  84.         (2)设置USART1两个管脚GPIO模式
  85.         (3)配置USART1数据格式、波特率等参数
  86.         (4)使能USART1接收中断功能
  87.         (5)最后使能USART1功能
  88. */
  89. void USART1_Configuration(void)
  90. {
  91.         GPIO_InitTypeDef GPIO_InitStructure;
  92.         USART_InitTypeDef USART_InitStructure;

  93.         /* 第1步:打开GPIO和USART部件的时钟 */
  94.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
  95.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

  96.         /* 第2步:将USART Tx的GPIO配置为推挽复用模式 */
  97.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  98.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  99.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  100.         GPIO_Init(GPIOA, &GPIO_InitStructure);

  101.         /* 第3步:将USART Rx的GPIO配置为浮空输入模式
  102.                 由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的
  103.                 但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数
  104.         */
  105.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  106.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  107.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  108.         /*  第3步已经做了,因此这步可以不做
  109.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  110.         */
  111.         GPIO_Init(GPIOA, &GPIO_InitStructure);


  112.         /* 第4步:配置USART1参数
  113.             - BaudRate = 115200 baud
  114.             - Word Length = 8 Bits
  115.             - One Stop Bit
  116.             - No parity
  117.             - Hardware flow control disabled (RTS and CTS signals)
  118.             - Receive and transmit enabled
  119.         */
  120.         USART_InitStructure.USART_BaudRate = 9600;
  121.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  122.         USART_InitStructure.USART_StopBits = USART_StopBits_1;
  123.         USART_InitStructure.USART_Parity = USART_Parity_No;
  124.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  125.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  126.         USART_Init(USART1, &USART_InitStructure);

  127.     /* 若接收数据寄存器满,则产生中断 */
  128.     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

  129.         /* 第5步:使能 USART1, 配置完毕 */
  130.         USART_Cmd(USART1, ENABLE);

  131.     /* 如下语句解决第1个字节无法正确发送出去的问题 */
  132.     USART_ClearFlag(USART1, USART_FLAG_TC);     // 清标志
  133. }

  134. /*******************************************************************/
  135. /*                                                                 */
  136. /* STM32向串口1发送1字节                                           */
  137. /*                                                                 */
  138. /*                                                                 */
  139. /*******************************************************************/
  140. /*void Uart1_PutChar(u8 ch)
  141. {
  142.   USART_SendData(USART1, (u8) ch);
  143.   while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  144. } */



  145. /*************************************************
  146. 函数: int main(void)
  147. 功能: main主函数
  148. 参数: 无
  149. 返回: 无
  150. **************************************************/
  151. int main(void)
  152. {
  153.   //u8 data;
  154.   RCC_Configuration();
  155.   NVIC_Configuration();
  156.   USART1_Configuration();
  157.   delay_init(72);
  158.   canid=1;        //这里的ID号根据发射机要发射的ID号来设置
  159.   CAN_Configuration();
  160.   while(1)
  161.   {
  162.          
  163.          //Can_Send_Msg(1,data);//发送的ID号要与接收机一致。
  164.          //data++;
  165.          //delay_ms(1000);
  166.          printf("接收到的数据 ReceiveData=%d\r\n",ReceiveData);         //ReceiveData为接收到发射机发来的数据,在CAN的中断函数里接收,在电脑串口中显示。
  167.          delay_ms(500);                                                                                                                  
  168.   }
  169. }
复制代码

发射机单片机源程序如下:
  1. /**************************************************************************************
  2.                 作者:蓝想电子
  3.                 功能介绍:发射机作用每一S钟变量data自动加1,加到255又重0开始,循环发射。
  4.                           接收机收到数据,在串口上显示.
  5.                 注意:接收机的ID号必须跟发射机发射的ID号一致。
  6. ****************************************************************************************/                        

  7. #include "stm32f10x.h"
  8. #include <stdio.h>
  9. #include "delay.h"
  10. #include "can.h"
  11. extern u32 canid;
  12. extern u8 ReceiveData;
  13. CanTxMsg TxMessage;
  14. u8 DY[8]={0x03,0xf0,0x00,0x21,0x44,0x16,0x00,0x00};
  15. //
  16. u8 GJ[8]={0x03,0xf0,0x00,0x35,0x00,0x01,0x00,0x00};
  17. //使用printf要在target里将 Use Micro LIB选中  必须加头文件stdio.h
  18. int fputc(int ch,FILE *f)
  19. {
  20.           USART_SendData(USART1, (u8) ch);
  21.       while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  22.           return ch;
  23. }

  24. /*************************************************
  25. 函数: void RCC_Configuration(void)
  26. 功能: 复位和时钟控制 配置
  27. 参数: 无
  28. 返回: 无
  29. **************************************************/
  30. void RCC_Configuration(void)
  31. {
  32.   ErrorStatus HSEStartUpStatus;                    //定义外部高速晶体启动状态枚举变量
  33.   RCC_DeInit();                                    //复位RCC外部设备寄存器到默认值
  34.   RCC_HSEConfig(RCC_HSE_ON);                       //打开外部高速晶振
  35.   HSEStartUpStatus = RCC_WaitForHSEStartUp();      //等待外部高速时钟准备好
  36.   if(HSEStartUpStatus == SUCCESS)                  //外部高速时钟已经准别好
  37.   {
  38.     FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //开启FLASH预读缓冲功能,加速FLASH的读取。所有程序中必须的用法.位置:RCC初始化子函数里面,时钟起振之后
  39.     FLASH_SetLatency(FLASH_Latency_2);                    //flash操作的延时
  40.               
  41.     RCC_HCLKConfig(RCC_SYSCLK_Div1);               //配置AHB(HCLK)时钟等于==SYSCLK
  42.     RCC_PCLK2Config(RCC_HCLK_Div1);                //配置APB2(PCLK2)钟==AHB时钟
  43.     RCC_PCLK1Config(RCC_HCLK_Div2);                //配置APB1(PCLK1)钟==AHB1/2时钟
  44.          
  45.     RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  //配置PLL时钟 == 外部高速晶体时钟 * 9 = 72MHz
  46.     RCC_PLLCmd(ENABLE);                                   //使能PLL时钟
  47.    
  48.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)    //等待PLL时钟就绪
  49.     {
  50.     }
  51.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);            //配置系统时钟 = PLL时钟
  52.     while(RCC_GetSYSCLKSource() != 0x08)                  //检查PLL时钟是否作为系统时钟
  53.     {
  54.     }
  55.   }

  56. }

  57. /*******************************************************************************
  58. * Function Name   : NVIC_Configuration
  59. * Description        : Configures NVIC and Vector Table base location.
  60. * Input                    : None
  61. * Output                 : None
  62. * Return                 : None
  63. *******************************************************************************/
  64. void NVIC_Configuration(void)
  65. {
  66.    NVIC_InitTypeDef NVIC_InitStructure;
  67.   
  68.    /* Set the Vector Table base location at 0x08000000 */
  69.    NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
  70.   
  71.    /* Configure the NVIC Preemption Priority Bits */  
  72.    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  73.   
  74.    /* Enable the USART1 Interrupt */
  75.    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;       //通道设置为串口1中断
  76.    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;           //中断响应优先级0
  77.    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                   //打开中断
  78.    NVIC_Init(&NVIC_InitStructure);                                                    //初始化
  79. }

  80. /*******************************************************************************
  81.         函数名:USART1_Configuration
  82.         输  入:
  83.         输  出:
  84.         功能说明:
  85.         初始化串口硬件设备,启用中断
  86.         配置步骤:
  87.         (1)打开GPIO和USART1的时钟
  88.         (2)设置USART1两个管脚GPIO模式
  89.         (3)配置USART1数据格式、波特率等参数
  90.         (4)使能USART1接收中断功能
  91.         (5)最后使能USART1功能
  92. */
  93. void USART1_Configuration(void)
  94. {
  95.         GPIO_InitTypeDef GPIO_InitStructure;
  96.         USART_InitTypeDef USART_InitStructure;

  97.         /* 第1步:打开GPIO和USART部件的时钟 */
  98.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
  99.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

  100.         /* 第2步:将USART Tx的GPIO配置为推挽复用模式 */
  101.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  102.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  103.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  104.         GPIO_Init(GPIOA, &GPIO_InitStructure);

  105.         /* 第3步:将USART Rx的GPIO配置为浮空输入模式
  106.                 由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的
  107.                 但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数
  108.         */
  109.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  110.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  111.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  112.         /*  第3步已经做了,因此这步可以不做
  113.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  114.         */
  115.         GPIO_Init(GPIOA, &GPIO_InitStructure);


  116.         /* 第4步:配置USART1参数
  117.             - BaudRate = 115200 baud
  118.             - Word Length = 8 Bits
  119.             - One Stop Bit
  120.             - No parity
  121.             - Hardware flow control disabled (RTS and CTS signals)
  122.             - Receive and transmit enabled
  123.         */
  124.         USART_InitStructure.USART_BaudRate = 115200;
  125.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  126.         USART_InitStructure.USART_StopBits = USART_StopBits_1;
  127.         USART_InitStructure.USART_Parity = USART_Parity_No;
  128.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  129.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  130.         USART_Init(USART1, &USART_InitStructure);

  131.     /* 若接收数据寄存器满,则产生中断 */
  132.     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

  133.         /* 第5步:使能 USART1, 配置完毕 */
  134.         USART_Cmd(USART1, ENABLE);

  135.     /* 如下语句解决第1个字节无法正确发送出去的问题 */
  136.     USART_ClearFlag(USART1, USART_FLAG_TC);     // 清标志
  137. }

  138. /*******************************************************************/
  139. /*                                                                 */
  140. /* STM32向串口1发送1字节                                           */
  141. /*                                                                 */
  142. /*                                                                 */
  143. /*******************************************************************/
  144. /*void Uart1_PutChar(u8 ch)
  145. {
  146.   USART_SendData(USART1, (u8) ch);
  147.   while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  148. } */



  149. /*************************************************
  150. 函数: int main(void)
  151. 功能: main主函数
  152. 参数: 无
  153. 返回: 无
  154. **************************************************/
  155. int main(void)
  156. {

  157.   RCC_Configuration();
  158.   NVIC_Configuration();
  159.   USART1_Configuration();
  160.   delay_init(72);
  161.   canid=1;        //这里的ID号根据发射机要发射的ID号来设置
  162.   CAN_Configuration();
  163.   while(1)
  164.   {
  165. ……………………

  166. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

程序很老,用的老版本的库:

STM32 CAN.7z (332.38 KB, 下载次数: 88)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表