当前位置:   article > 正文

STM32的IO模拟串口

STM32的IO模拟串口

串口的时序就不再多讲了,主要是分享一个比自己写的IO模拟串口的实例

申明:

这个波特率为115200

分频系数为8

自动重载值为68

约等于8.7微秒

使用其他波特率或者IO口,只需要修改.h文件中的对应参数即可

头文件

  1. #ifndef IO_UART_H
  2. #define IO_UART_H
  3. #include "tim.h"
  4. enum
  5. {
  6. N_CMD, //空闲
  7. W_CMD, //
  8. R_CMD, //
  9. F_CMD, //完成
  10. };
  11. enum
  12. {
  13. UNWAIT,
  14. WAITING,
  15. };
  16. #define U_TIM TIM4 //UART内部定时器
  17. #define TX_GPIO_PIN GPIO_PIN_15 //UART对应的TX引脚
  18. #define RX_GPIO_PIN GPIO_PIN_14 //UART对应的RX引脚
  19. #define TX_PIN 14 //UART对应的TX引脚编号
  20. #define RX_PIN 15 //UART对应的RX引脚编号
  21. #define TX_GPIO GPIOB //UART对应的TX端口
  22. #define RX_GPIO GPIOB //UART对应的RX端口
  23. #define MAX_WAIT 0x5 //最大等待时间
  24. #define T_RELOAD 68 //发送一个字节所需的时间
  25. #define T_FIRST 0x33 //延时到第一位的时间
  26. #define MAX_BUFSIZE 3000 //收发最大字符数量
  27. /************************************
  28. function : 定时器中断回调函数
  29. ************************************/
  30. void TIM_UART_Callback(TIM_HandleTypeDef *htim);
  31. /************************************
  32. function : 外部中断回调函数
  33. ************************************/
  34. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
  35. /************************************
  36. function : 发送一个字节
  37. input : uint8_t send_data //要发送的字节
  38. return : void
  39. ************************************/
  40. void SEND_BYTE(uint8_t send_data);
  41. /************************************
  42. function : 发送一个字符串
  43. input : uint8_t *send_data //要发送的字符串
  44. return : void
  45. ************************************/
  46. void SEND_STRING(uint8_t *send_data);
  47. /************************************
  48. function : 等待读取一个字符串
  49. input : uint8_t *read_data //接收目标字符串
  50. return : void
  51. ************************************/
  52. void READ_STRING(uint8_t *read_data);
  53. /************************************
  54. function : 清空一个字符串
  55. input : uint8_t *string //要清楚的字符串 size_t str_len //清除字符串的长度
  56. return : void
  57. ************************************/
  58. void ZERO_STRING(uint8_t *string,size_t str_len);
  59. /************************************
  60. function : UART初始化
  61. input : void
  62. return : void
  63. ************************************/
  64. void UART_INIT(void);
  65. #endif

.c文件

  1. #include "io_uart.h"
  2. volatile uint8_t uart_flag = N_CMD;
  3. uint8_t cnt_bit = 0;
  4. uint8_t uart_data = 0;
  5. uint8_t wait_flag = UNWAIT;
  6. uint8_t **buf = NULL;
  7. uint32_t i = 0;
  8. /************************************
  9. function : 拉高TXD
  10. ************************************/
  11. static void SET_TXD(void)
  12. {
  13. TX_GPIO->BSRR = TX_GPIO_PIN;
  14. }
  15. /************************************
  16. function : 拉低TXD
  17. ************************************/
  18. static void RESET_TXD(void)
  19. {
  20. TX_GPIO->BSRR = (uint32_t)TX_GPIO_PIN << 16u;
  21. }
  22. /************************************
  23. function : 读取RXD电平
  24. ************************************/
  25. static uint8_t READ_RXD(void)
  26. {
  27. return ((RX_GPIO->IDR & RX_GPIO_PIN) >> TX_PIN);
  28. }
  29. /************************************
  30. function : 定时器中断回调函数
  31. ************************************/
  32. void TIM_UART_Callback(TIM_HandleTypeDef *htim)
  33. {
  34. //写一个字节
  35. if(uart_flag == W_CMD)
  36. {
  37. if(cnt_bit == 0)
  38. {
  39. //拉低TXD
  40. RESET_TXD();
  41. }
  42. else if(cnt_bit > 0 && cnt_bit < 9)
  43. {
  44. if(uart_data & (0x01 << (cnt_bit - 1)))
  45. {
  46. //输出高电平
  47. SET_TXD();
  48. }
  49. else
  50. {
  51. //输出低电平
  52. RESET_TXD();
  53. }
  54. }
  55. else
  56. {
  57. //拉高TXD
  58. SET_TXD();
  59. cnt_bit = 0;
  60. uart_flag = N_CMD;
  61. uart_data = 0;
  62. //关闭定时器中断
  63. U_TIM->CR1 &= ~(TIM_CR1_CEN);
  64. return;
  65. }
  66. cnt_bit++;
  67. }
  68. //读一个字节
  69. else if(uart_flag == R_CMD)
  70. {
  71. if(cnt_bit == 0)
  72. {
  73. //设置定时器定时时间
  74. U_TIM->ARR = T_RELOAD;
  75. }
  76. else if(cnt_bit == 8)
  77. {
  78. cnt_bit = 0;
  79. /****new****/
  80. //设置定时器定时时间
  81. U_TIM->CNT = 0x00;
  82. U_TIM->ARR = T_RELOAD*MAX_WAIT;
  83. (*buf)[i] = uart_data;
  84. i++;
  85. uart_data = 0;
  86. wait_flag = WAITING;
  87. cnt_bit = 0;
  88. //打开外部中断
  89. EXTI->PR = (RX_GPIO_PIN);
  90. EXTI->IMR |= (0x1 << TX_PIN);
  91. /****new****/
  92. return;
  93. }
  94. uart_data |= (READ_RXD() << cnt_bit);
  95. cnt_bit++;
  96. //判断是否读取完成
  97. if(wait_flag == WAITING)
  98. {
  99. //读取完成
  100. uart_flag = F_CMD;
  101. wait_flag = UNWAIT;
  102. //关闭定时器中断
  103. U_TIM->CR1 &= ~(TIM_CR1_CEN);
  104. //关闭外部中断
  105. EXTI->IMR &= ~(0x1 << TX_PIN);
  106. return;
  107. }
  108. }
  109. }
  110. /************************************
  111. function : 外部中断回调函数
  112. ************************************/
  113. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  114. {
  115. switch(GPIO_Pin)
  116. {
  117. case RX_GPIO_PIN:
  118. EXTI->PR = (RX_GPIO_PIN);
  119. if(uart_flag != R_CMD)
  120. return;
  121. else
  122. {
  123. wait_flag = UNWAIT;
  124. //关闭定时器中断
  125. U_TIM->CR1 &= ~(TIM_CR1_CEN);
  126. //设置定时器定时时间
  127. U_TIM->CNT = 0x00;
  128. U_TIM->ARR = T_FIRST;
  129. //打开定时器中断
  130. U_TIM->SR = ~(TIM_IT_UPDATE);
  131. U_TIM->CR1 |= (TIM_CR1_CEN);
  132. //关闭外部中断
  133. EXTI->IMR &= ~(0x1 << TX_PIN);
  134. EXTI->PR = (RX_GPIO_PIN);
  135. }
  136. break;
  137. default:
  138. break;
  139. }
  140. }
  141. /************************************
  142. function : 发送一个字节
  143. input : uint8_t send_data //要发送的字节
  144. return : void
  145. ************************************/
  146. void SEND_BYTE(uint8_t send_data)
  147. {
  148. while(uart_flag != N_CMD);
  149. uart_flag = W_CMD;
  150. cnt_bit = 0;
  151. uart_data = send_data;
  152. //打开定时器中断
  153. U_TIM->SR = ~(TIM_IT_UPDATE);
  154. U_TIM->CR1 |= (TIM_CR1_CEN);
  155. while(uart_flag != N_CMD);
  156. }
  157. /************************************
  158. function : 发送一个字符串
  159. input : uint8_t *send_data //要发送的字符串
  160. return : void
  161. ************************************/
  162. void SEND_STRING(uint8_t *send_data)
  163. {
  164. uint32_t j = 0;
  165. for(j = 0; (send_data[j] != 0 || send_data[j+1] != 0) && i < MAX_BUFSIZE-1; j++)
  166. {
  167. SEND_BYTE(send_data[j]);
  168. }
  169. }
  170. /************************************
  171. function : 等待读取一个字符串
  172. input : uint8_t *read_data //接收目标字符串
  173. return : void
  174. ************************************/
  175. void READ_STRING(uint8_t *read_data)
  176. {
  177. while(uart_flag != N_CMD);
  178. i = 0;
  179. buf = &read_data;
  180. cnt_bit = 0;
  181. uart_flag = R_CMD;
  182. //打开外部中断
  183. EXTI->PR = (RX_GPIO_PIN);
  184. EXTI->IMR |= (0x1 << TX_PIN);
  185. while(uart_flag != F_CMD);
  186. //read_data[255] read_data[254] read_data[256] read_data[258] read_data[0] read_data[1]
  187. buf = NULL;
  188. uart_data = 0;
  189. cnt_bit = 0;
  190. uart_flag = N_CMD;
  191. }
  192. /************************************
  193. function : 清空一个字符串
  194. input : uint8_t *string //要清楚的字符串 size_t str_len //清除字符串的长度
  195. return : void
  196. ************************************/
  197. void ZERO_STRING(uint8_t *string,size_t str_len)
  198. {
  199. int i = 0;
  200. for(i = 0; i < str_len; i++)
  201. {
  202. string[i] = 0;
  203. }
  204. return;
  205. }
  206. /************************************
  207. function : UART初始化
  208. input : void
  209. return : void
  210. ************************************/
  211. void UART_INIT(void)
  212. {
  213. //清空定时器中断标志位
  214. U_TIM->SR = ~(TIM_IT_UPDATE);
  215. //关闭定时器中断
  216. U_TIM->DIER |= (TIM_IT_UPDATE);
  217. U_TIM->CR1 &= ~(TIM_CR1_CEN);
  218. //关闭外部中断
  219. EXTI->IMR &= ~(0x1 << TX_PIN);
  220. //清空外部中断标志位
  221. EXTI->PR = (RX_GPIO_PIN);
  222. }
  223. //

/************************************
function : 定时器中断回调函数
************************************/
void TIM_UART_Callback(TIM_HandleTypeDef *htim);这个定时器回调函数写在对应的HAL的回调函数中,

/************************************
function : 外部中断回调函数 
************************************/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);如果使用了其他的外部中断,可以像定时器中断那样改一个名字后放入对应的HAL库的外部中断函数中

 如果程序出现了什么问题,欢迎和我交流

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

闽ICP备14008679号