当前位置:   article > 正文

树莓派与stm32进行串口通信_一块电池给32和树莓派同时供电

一块电池给32和树莓派同时供电

      目前很多大学电子类的比赛中,进行通信的大部分是用到串口进行通信,因此打算出一期有关stm32与树莓派进行通信的博客,目前这是第一篇,因此这一篇博客主要简单讲讲stm32的串口通信,其中包含硬件的接线图,以及相关程序,后续有时间会继续出stm32与树莓派的串口通信,原理都是一样的。

        与其他博客不相同的地方在于,对于串口的解释上我不作过多解释,重点主要在于能“拿来就用”,以及我在使用stm32时候所踩过的坑。代码来源B站江科大自化协、以及正点原子,若有不懂地方建议观看江协科技相关视频

        通信的总类大概可以分为以下几类:

        而大学期间常用的是前三种,USART、I2C以及SPI

       这里主要讲讲USART,串口通信下面是引脚接线图:

        其中当两个设备分别用不同电源供电的时候,需要共地,其原因在于,串口通信的原理为发送一个8bit位的0和1,然后另一端进行解码、得出传输的数据,共地的意义在于规定多大的电压为0。

        串口通信需要相同的波特率,波特率相同的意义在于,让两个设备处于相同的“频道”,当波特率不同时,两个设备无法进行通信。

        总结:串口通信引脚接线不是相同名字接一起,RX与TX反接,不同的供电系统需要供地,两个设备的波特率需要相同。

        接下来是程序部分:

我使用的是stm32的串口1,其中的.c文件

  1. #include "sys.h"
  2. #include "usart.h"
  3. #include <stdarg.h>
  4. //
  5. //如果使用ucos,则包括下面的头文件即可.
  6. #if SYSTEM_SUPPORT_OS
  7. #include "includes.h" //ucos 使用
  8. #endif
  9. //
  10. //本程序只供学习使用,未经作者许可,不得用于其它任何用途
  11. //ALIENTEK STM32开发板
  12. //串口1初始化
  13. //正点原子@ALIENTEK
  14. //技术论坛:www.openedv.com
  15. //修改日期:2012/8/18
  16. //版本:V1.5
  17. //版权所有,盗版必究。
  18. //Copyright(C) 广州市星翼电子科技有限公司 2009-2019
  19. //All rights reserved
  20. //********************************************************************************
  21. //V1.3修改说明
  22. //支持适应不同频率下的串口波特率设置.
  23. //加入了对printf的支持
  24. //增加了串口接收命令功能.
  25. //修正了printf第一个字符丢失的bug
  26. //V1.4修改说明
  27. //1,修改串口初始化IO的bug
  28. //2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方
  29. //3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方)
  30. //4,修改了EN_USART1_RX的使能方式
  31. //V1.5修改说明
  32. //1,增加了对UCOSII的支持
  33. //
  34. //
  35. //加入以下代码,支持printf函数,而不需要选择use MicroLIB
  36. #if 1
  37. #pragma import(__use_no_semihosting)
  38. //标准库需要的支持函数
  39. struct __FILE
  40. {
  41. int handle;
  42. };
  43. FILE __stdout;
  44. //定义_sys_exit()以避免使用半主机模式
  45. void _sys_exit(int x)
  46. {
  47. x = x;
  48. }
  49. //重定义fputc函数
  50. int fputc(int ch, FILE *f)
  51. {
  52. while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
  53. USART1->DR = (u8) ch;
  54. return ch;
  55. }
  56. #endif
  57. #if EN_USART1_RX //如果使能了接收
  58. //串口1中断服务程序
  59. //注意,读取USARTx->SR能避免莫名其妙的错误
  60. u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
  61. //接收状态
  62. //bit15, 接收完成标志
  63. //bit14, 接收到0x0d
  64. //bit13~0, 接收到的有效字节数目
  65. u16 USART_RX_STA=0; //接收状态标记
  66. char Serial_RxPacket[100]; //"@MSG\r\n"
  67. uint8_t Serial_RxFlag;
  68. void uart_init(u32 bound)
  69. {
  70. //GPIO端口设置
  71. GPIO_InitTypeDef GPIO_InitStructure;
  72. USART_InitTypeDef USART_InitStructure;
  73. NVIC_InitTypeDef NVIC_InitStructure;
  74. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
  75. //USART1_TX GPIOA.9
  76. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  77. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  78. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
  79. GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
  80. //USART1_RX GPIOA.10初始化
  81. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  82. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  83. GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
  84. //Usart1 NVIC 配置
  85. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  86. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
  87. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级3
  88. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
  89. NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
  90. //USART 初始化设置
  91. USART_InitStructure.USART_BaudRate = bound;//串口波特率
  92. USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  93. USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  94. USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  95. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  96. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
  97. USART_Init(USART1, &USART_InitStructure); //初始化串口1
  98. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  99. USART_Cmd(USART1, ENABLE); //使能串口1
  100. }
  101. void Serial_SendByte(uint8_t Byte)
  102. {
  103. USART_SendData(USART1, Byte);
  104. while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  105. }
  106. void Serial_SendArray(uint8_t *Array, uint16_t Length)
  107. {
  108. uint16_t i;
  109. for (i = 0; i < Length; i ++)
  110. {
  111. Serial_SendByte(Array[i]);
  112. }
  113. }
  114. void Serial_SendString(char *String)
  115. {
  116. uint8_t i;
  117. for (i = 0; String[i] != '\0'; i ++)
  118. {
  119. Serial_SendByte(String[i]);
  120. }
  121. }
  122. uint32_t Serial_Pow(uint32_t X, uint32_t Y)
  123. {
  124. uint32_t Result = 1;
  125. while (Y --)
  126. {
  127. Result *= X;
  128. }
  129. return Result;
  130. }
  131. void Serial_SendNumber(uint32_t Number, uint8_t Length)
  132. {
  133. uint8_t i;
  134. for (i = 0; i < Length; i ++)
  135. {
  136. Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
  137. }
  138. }
  139. void Serial_Printf(char *format, ...)
  140. {
  141. char String[100];
  142. va_list arg;
  143. va_start(arg, format);
  144. vsprintf(String, format, arg);
  145. va_end(arg);
  146. Serial_SendString(String);
  147. }
  148. void USART1_IRQHandler(void) //串口1中断服务程序
  149. {
  150. static uint8_t RxState = 0;
  151. static uint8_t pRxPacket = 0;
  152. if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
  153. {
  154. uint8_t RxData = USART_ReceiveData(USART1);
  155. if (RxState == 0)
  156. {
  157. if (RxData == '{' && Serial_RxFlag == 0)
  158. {
  159. RxState = 1;
  160. pRxPacket = 0;
  161. }
  162. }
  163. else if (RxState == 1)
  164. {
  165. if (RxData == '}')
  166. {
  167. RxState = 2;
  168. }
  169. else
  170. {
  171. Serial_RxPacket[pRxPacket] = RxData;
  172. pRxPacket ++;
  173. }
  174. }
  175. else if (RxState == 2)
  176. {
  177. if (RxData == '\n')
  178. {
  179. RxState = 0;
  180. Serial_RxPacket[pRxPacket] = '\0';
  181. Serial_RxFlag = 1;
  182. }
  183. }
  184. USART_ClearITPendingBit(USART1, USART_IT_RXNE);
  185. }
  186. }
  187. #endif

 其中的.h文件

  1. #ifndef __USART_H
  2. #define __USART_H
  3. #include "stdio.h"
  4. #include "sys.h"
  5. //
  6. //本程序只供学习使用,未经作者许可,不得用于其它任何用途
  7. //ALIENTEK STM32开发板
  8. //串口1初始化
  9. //正点原子@ALIENTEK
  10. //技术论坛:www.openedv.com
  11. //修改日期:2012/8/18
  12. //版本:V1.5
  13. //版权所有,盗版必究。
  14. //Copyright(C) 广州市星翼电子科技有限公司 2009-2019
  15. //All rights reserved
  16. //********************************************************************************
  17. //V1.3修改说明
  18. //支持适应不同频率下的串口波特率设置.
  19. //加入了对printf的支持
  20. //增加了串口接收命令功能.
  21. //修正了printf第一个字符丢失的bug
  22. //V1.4修改说明
  23. //1,修改串口初始化IO的bug
  24. //2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方
  25. //3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方)
  26. //4,修改了EN_USART1_RX的使能方式
  27. //V1.5修改说明
  28. //1,增加了对UCOSII的支持
  29. #define USART_REC_LEN 200 //定义最大接收字节数 200
  30. #define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收
  31. extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
  32. extern u16 USART_RX_STA; //接收状态标记
  33. //如果想串口中断接收,请不要注释以下宏定义
  34. void uart_init(u32 bound);
  35. extern char Serial_RxPacket[];
  36. extern uint8_t Serial_RxFlag;
  37. void Serial_SendByte(uint8_t Byte);
  38. void Serial_SendArray(uint8_t *Array, uint16_t Length);
  39. void Serial_SendString(char *String);
  40. void Serial_SendNumber(uint32_t Number, uint8_t Length);
  41. void Serial_Printf(char *format, ...);
  42. #endif

我是在正点原子的基础上进行修改

接下来是使用的例程:

 uart_init(),其中括号里面的就是波特率,具体多少根据实际情形进行修改

if (Serial_RxFlag == 1)表示如果收到消息

if (Serial_RxPacket[i]=='1')su_1(180,40+70*i,80,10);如果收到的数据是字符串"1"

其中我所收到的数据包头必须为前大括号{,包尾必须为后大括号},最后还需要以换行符结尾\n,而我们所收到的数据中只包含括号里面的东西,例如设备1想要发送字符串123+213,实际发送的说时候应该为{123+213}\n

当我们收到消息后Serial_RxFlag自动转换为1,Serial_RxPacket[1]='1',或者可以用1所对应的ASCLL码进行判断,后续也可以进行相关的处理

发送字符串可以用void Serial_Printf(char *format, ...);函数进行字符串的发送

例如设备1发送字符串ABC,设备2收到后进行相关的处理

  1. 设备1
  2. #相关头文件
  3. int  main(void)
  4. {
  5.  uart_init(115200);
  6. while1
  7. {
  8. Serial_Printf(“{ABC}\n”);
  9. }
  10. }
  11. 这样设备1就能使用串口1进行发送ABC数据
  12. 设备2
  13. #头文件
  14. int  main(void)
  15. {
  16.  uart_init(115200);
  17. while1
  18. {
  19. if (Serial_RxFlag == 1);
  20. {
  21. if (strcmp(Serial_RxPacket, "ABC") == 0)
  22. {
  23. 进行相关处理
  24. }
  25. Serial_RxFlag == 0
  26. }
  27. }
  28. }

strcmp(Serial_RxPacket, "QIAN") == 0使用这个函数需要包含头文件#include "string.h"

我的头文件包含情况:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/689148
推荐阅读
相关标签
  

闽ICP备14008679号