前言
这一部分的学习完全不知道原理是很难写好代码的,这篇博客主要通过代码实现的方式叙述,在不需要理解原理的部分直接套用模板代码,按照模板书写容易出错的地方我会加以说明,目的是能在最少时间理解原理的条件下快速的使用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。两种方式只能选择之一。