STM32F103C8 串口的使用

简介: STM32F103C8 串口的使用

前言

这一部分的学习完全不知道原理是很难写好代码的,这篇博客主要通过代码实现的方式叙述,在不需要理解原理的部分直接套用模板代码,按照模板书写容易出错的地方我会加以说明,目的是能在最少时间理解原理的条件下快速的使用STM32


一、配置步骤

第一步:开启时钟,把需要用的USAART和GPIO的时钟打开

第二步:GPIO初始化,把TX配置成复用输出,RX配置成输入

第三步:配置USART

第四步:如果只需要发送的功能就直接开启USART,如果需要接收功能则还需要配置中断

*TX引脚是USART外设控制的输出脚,要用复用推挽输出,RX是USART外设数据输入脚,要用输入模式,其中TX  RX都在GPIO具体的引脚里,查引脚定义表可以得知

二、具体代码

1、串口发送数据

1. #include "stm32f10x.h"                  // Device header
2. #include <stdio.h>
3. #include <stdarg.h>
4. 
5. void Serial_Init(void)
6. {
7.  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
8.  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
9. 
10.   GPIO_InitTypeDef GPIO_InitStructure;
11.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
12.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
13.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
14.   GPIO_Init(GPIOA, &GPIO_InitStructure);
15. 
16.   USART_InitTypeDef USART_InitStructure;
17.   USART_InitStructure.USART_BaudRate = 9600;
18.   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
19.   USART_InitStructure.USART_Mode = USART_Mode_Tx;
20.   USART_InitStructure.USART_Parity = USART_Parity_No;
21.   USART_InitStructure.USART_StopBits = USART_StopBits_1;
22.   USART_InitStructure.USART_WordLength = USART_WordLength_8b;
23.   USART_Init(USART1, &USART_InitStructure);
24. 
25.   USART_Cmd(USART1, ENABLE);
26. }
27. 
28. void Serial_SendByte(uint8_t Byte)//发送一位数字
29. {
30.   USART_SendData(USART1, Byte);
31.   while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
32. }
33. 
34. void Serial_SendArray(uint8_t *Array, uint16_t Length)//发送一个数组   参数:数组地址    数组长度
35. {
36.   uint16_t i;
37.   for (i = 0; i < Length; i ++)
38.   {
39.     Serial_SendByte(Array[i]);
40.   }
41. }
42. 
43. void Serial_SendString(char *String)//发送一个字符串
44. {
45.   uint8_t i;
46.   for (i = 0; String[i] != '\0'; i ++)
47.   {
48.     Serial_SendByte(String[i]);
49.   }
50. }
51. 
52. uint32_t Serial_Pow(uint32_t X, uint32_t Y)
53. {
54.   uint32_t Result = 1;
55.   while (Y --)
56.   {
57.     Result *= X;
58.   }
59.   return Result;
60. }
61. 
62. void Serial_SendNumber(uint32_t Number, uint8_t Length)//发送一个数字     参数:数字   数字长度
63. {
64.   uint8_t i;
65.   for (i = 0; i < Length; i ++)
66.   {
67.     Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
68.   }
69. }
70. 
71. int fputc(int ch, FILE *f)
72. {
73.   Serial_SendByte(ch);
74.   return ch;
75. }
76. 
77. void Serial_Printf(char *format, ...)//可以看成多串口都能用的串口上的printf,记住调用时前一个函数fputc也得一起使用
78. {
79.   char String[100];
80.   va_list arg;
81.   va_start(arg, format);
82.   vsprintf(String, format, arg);
83.   va_end(arg);
84.   Serial_SendString(String);
85. }
1. #include "stm32f10x.h"                  // Device header
2. #include "Delay.h"
3. #include "OLED.h"
4. #include "Serial.h"
5. 
6. int main(void)
7. {
8.  OLED_Init();
9. 
10.   Serial_Init();
11. 
12.   Serial_SendByte(0x41);
13. 
14.   uint8_t MyArray[] = {0x42, 0x43, 0x44, 0x45};
15.   Serial_SendArray(MyArray, 4);
16. 
17.   Serial_SendString("\r\nNum1=");
18. 
19.   Serial_SendNumber(111, 3);
20. 
21.   printf("\r\nNum2=%d", 222);
22. 
23.   char String[100];
24.   sprintf(String, "\r\nNum3=%d", 333);
25.   Serial_SendString(String);
26. 
27.   Serial_Printf("\r\nNum4=%d", 444);
28.   Serial_Printf("\r\n");
29. 
30.   while (1)
31.   {
32. 
33.   }
34. }

2、串口收发hex数据包

1. #include "stm32f10x.h"                  // Device header
2. #include <stdio.h>
3. #include <stdarg.h>
4. 
5. uint8_t Serial_TxPacket[4];        //FF 01 02 03 04 FE
6. uint8_t Serial_RxPacket[4];
7. uint8_t Serial_RxFlag;
8. 
9. void Serial_Init(void)
10. {
11.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
12.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
13. 
14.   GPIO_InitTypeDef GPIO_InitStructure;
15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
16.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
17.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
18.   GPIO_Init(GPIOA, &GPIO_InitStructure);
19. 
20.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
21.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
22.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
23.   GPIO_Init(GPIOA, &GPIO_InitStructure);
24. 
25.   USART_InitTypeDef USART_InitStructure;
26.   USART_InitStructure.USART_BaudRate = 9600;
27.   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
28.   USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
29.   USART_InitStructure.USART_Parity = USART_Parity_No;
30.   USART_InitStructure.USART_StopBits = USART_StopBits_1;
31.   USART_InitStructure.USART_WordLength = USART_WordLength_8b;
32.   USART_Init(USART1, &USART_InitStructure);
33. 
34.   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
35. 
36.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
37. 
38.   NVIC_InitTypeDef NVIC_InitStructure;
39.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
40.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
41.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
42.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
43.   NVIC_Init(&NVIC_InitStructure);
44. 
45.   USART_Cmd(USART1, ENABLE);
46. }
47. 
48. void Serial_SendByte(uint8_t Byte)//发送一位数字
49. {
50.   USART_SendData(USART1, Byte);
51.   while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
52. }
53. 
54. void Serial_SendArray(uint8_t *Array, uint16_t Length)//发送一个数组   参数:数组地址    数组长度
55. {
56.   uint16_t i;
57.   for (i = 0; i < Length; i ++)
58.   {
59.     Serial_SendByte(Array[i]);
60.   }
61. }
62. 
63. void Serial_SendString(char *String)//发送一个字符串
64. {
65.   uint8_t i;
66.   for (i = 0; String[i] != '\0'; i ++)
67.   {
68.     Serial_SendByte(String[i]);
69.   }
70. }
71. 
72. uint32_t Serial_Pow(uint32_t X, uint32_t Y)
73. {
74.   uint32_t Result = 1;
75.   while (Y --)
76.   {
77.     Result *= X;
78.   }
79.   return Result;
80. }
81. 
82. void Serial_SendNumber(uint32_t Number, uint8_t Length)//发送一个数字     参数:数字   数字长度
83. {
84.   uint8_t i;
85.   for (i = 0; i < Length; i ++)
86.   {
87.     Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
88.   }
89. }
90. 
91. int fputc(int ch, FILE *f)
92. {
93.   Serial_SendByte(ch);
94.   return ch;
95. }
96. 
97. void Serial_Printf(char *format, ...)//可以看成多串口都能用的串口上的printf,记住调用时前一个函数fputc也得一起使用
98. {
99.   char String[100];
100.  va_list arg;
101.  va_start(arg, format);
102.  vsprintf(String, format, arg);
103.  va_end(arg);
104.  Serial_SendString(String);
105. }
106. 
107. 
108. void Serial_SendPacket(void)
109. {
110.  Serial_SendByte(0xFF);
111.  Serial_SendArray(Serial_TxPacket, 4);
112.  Serial_SendByte(0xFE);
113. }
114. 
115. uint8_t Serial_GetRxFlag(void)
116. {
117.  if (Serial_RxFlag == 1)
118.  {
119.    Serial_RxFlag = 0;
120.    return 1;
121.  }
122.  return 0;
123. }
124. 
125. void USART1_IRQHandler(void)
126. {
127.  static uint8_t RxState = 0;
128.  static uint8_t pRxPacket = 0;
129.  if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
130.  {
131.    uint8_t RxData = USART_ReceiveData(USART1);
132. 
133.    if (RxState == 0)
134.    {
135.      if (RxData == 0xFF)
136.      {
137.        RxState = 1;
138.        pRxPacket = 0;
139.      }
140.    }
141.    else if (RxState == 1)
142.    {
143.      Serial_RxPacket[pRxPacket] = RxData;
144.      pRxPacket ++;
145.      if (pRxPacket >= 4)
146.      {
147.        RxState = 2;
148.      }
149.    }
150.    else if (RxState == 2)
151.    {
152.      if (RxData == 0xFE)
153.      {
154.        RxState = 0;
155.        Serial_RxFlag = 1;
156.      }
157.    }
158. 
159.    USART_ClearITPendingBit(USART1, USART_IT_RXNE);
160.  }
161. }
1. #include "stm32f10x.h"                  // Device header
2. #include "Delay.h"
3. #include "OLED.h"
4. #include "Serial.h"
5. #include "Key.h"
6. 
7. uint8_t KeyNum;
8. 
9. int main(void)
10. {
11.   OLED_Init();
12.   Key_Init();
13.   Serial_Init();//包头FF 包尾FE
14. 
15.   OLED_ShowString(1, 1, "TxPacket");
16.   OLED_ShowString(3, 1, "RxPacket");
17. 
18.   Serial_TxPacket[0] = 0x01;
19.   Serial_TxPacket[1] = 0x02;
20.   Serial_TxPacket[2] = 0x03;
21.   Serial_TxPacket[3] = 0x04;
22. 
23.   while (1)
24.   {
25.     KeyNum = Key_GetNum();
26.     if (KeyNum == 1)
27.     {
28.       Serial_TxPacket[0] ++;
29.       Serial_TxPacket[1] ++;
30.       Serial_TxPacket[2] ++;
31.       Serial_TxPacket[3] ++;
32. 
33.       Serial_SendPacket();
34. 
35.       OLED_ShowHexNum(2, 1, Serial_TxPacket[0], 2);
36.       OLED_ShowHexNum(2, 4, Serial_TxPacket[1], 2);
37.       OLED_ShowHexNum(2, 7, Serial_TxPacket[2], 2);
38.       OLED_ShowHexNum(2, 10, Serial_TxPacket[3], 2);
39.     }
40. 
41.     if (Serial_GetRxFlag() == 1)//这是触发输入的主要句子
42.     {
43.       OLED_ShowHexNum(4, 1, Serial_RxPacket[0], 2);
44.       OLED_ShowHexNum(4, 4, Serial_RxPacket[1], 2);
45.       OLED_ShowHexNum(4, 7, Serial_RxPacket[2], 2);
46.       OLED_ShowHexNum(4, 10, Serial_RxPacket[3], 2);
47.     }
48.   }
49. }

总结

如果想使用printf等c语言的精简库时需要点击魔术棒并将里面的Use MicoLIB打上勾

如果想实现中文打印不乱码,第一种方法打开魔术棒 c/c++选项的Misc Controls里填上--no-multibyte-chars。第二种方法是打开设置的encoding里选择GB2312编码,把当前存在的汉子删掉,关闭当前页面再打开,出现字体为宋体时才换为GB2312编码,这种编码方式串口助手里对应的是GBK。两种方式只能选择之一。

相关文章
STM32串口编程基础知识讲解
STM32串口编程基础知识讲解
102 0
|
4月前
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
714 0
|
4月前
STM32CubeMX 串口收发一帧数据
STM32CubeMX 串口收发一帧数据
56 9
|
4月前
|
芯片
STM32CubeMX 串口数据收发
STM32CubeMX 串口数据收发
144 2
|
4月前
|
监控
stm32f407探索者开发板(十八)——串口通信实验讲解(USART_RX_STA流程图详解)
stm32f407探索者开发板(十八)——串口通信实验讲解(USART_RX_STA流程图详解)
313 0
STM32(HAL库)驱动GY30光照传感器通过串口进行打印
STM32(HAL库)驱动GY30光照传感器通过串口进行打印
|
6月前
|
存储 缓存 芯片
STM32--USART串口
STM32--USART串口
108 0
|
6月前
|
Java C语言
STM32使用printf重定向到USART(串口)并打印数据到串口助手
STM32使用printf重定向到USART(串口)并打印数据到串口助手
323 0