• 串口发送&串口发送+接收&串口收发HEX数据包&串口收发文本数据包----USART


    目录

    printf函数移植方法

    显示汉字

    串口发送

    串口发送+接收

    串口收发HEX数据包

    串口收发文本数据包


    printf函数移植方法

    1.  printf只能一个串口使用且需要重定向到串口
    1. //重定向到串口
    2. int fputc(int ch,FILE *f)
    3. {
    4. Serial_SendByte(ch);
    5. return ch;
    6. }

    2. 多串口可以使用sprintf

    1. char String[100];
    2. sprintf(String,"Num=%d\r\n",666);//可以指定打印位置,不涉及重定向
    3. Serial_SendString(String);

    3. 封装sprintf

    头文件

    1. /**
    2. * @brief
    3. * @param 参数1:格式化字符串 参数二:接受可变参数列表
    4. * @retval
    5. */
    6. void Serial_Printf(char *format,...)
    7. {
    8. char String[100];
    9. va_list arg; //定义一个参数列表变量
    10. va_start(arg,format);
    11. vsprintf(String,format,arg);
    12. va_end(arg);
    13. Serial_SendString(String);
    14. }

    显示汉字

    方法1:keil和串口助手都选择utf-8,且keil加上--no-multibyte-chars参数

    方法2:都是用GB开头的中文编码格式,参数不用加

    串口发送

    1. #include "stm32f10x.h" // Device header
    2. #include <stdio.h>
    3. #include <stdarg.h>
    4. void Serial_Init(void)
    5. {
    6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //USART1在APB2
    7. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    8. GPIO_InitTypeDef GPIO_InitStructure;
    9. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
    10. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; //要看具体的引脚对应
    11. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    12. GPIO_Init(GPIOA,&GPIO_InitStructure);
    13. USART_InitTypeDef USART_InitStruct;
    14. //写完波特率,init函数内部会自动算好波特率对应的分频系数写到BRR寄存器
    15. USART_InitStruct.USART_BaudRate=9600;
    16. USART_InitStruct.USART_HardwareFlowControl= USART_HardwareFlowControl_None;
    17. USART_InitStruct.USART_Mode=USART_Mode_Tx;
    18. USART_InitStruct.USART_Parity=USART_Parity_No;
    19. USART_InitStruct.USART_StopBits=USART_StopBits_1;
    20. USART_InitStruct.USART_WordLength=USART_WordLength_8b;
    21. USART_Init(USART1,&USART_InitStruct);
    22. USART_Cmd(USART1,ENABLE);
    23. }
    24. void Serial_SendByte(uint8_t byte)
    25. {
    26. USART_SendData(USART1, byte);
    27. while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    28. }
    29. void Serial_SendArray(uint8_t *Array,uint16_t Length)
    30. {
    31. uint16_t i;
    32. for(i=0;i<Length;i++)
    33. {
    34. Serial_SendByte(Array[i]);
    35. }
    36. }
    37. void Serial_SendString(char *String)
    38. {
    39. uint8_t i;
    40. for(i=0;String[i]!='\0';i++)
    41. {
    42. Serial_SendByte(String[i]);
    43. }
    44. }
    45. uint32_t Serial_Pow(uint32_t x,uint32_t y)
    46. {
    47. uint32_t result =1;
    48. while(y--){
    49. result*=x;
    50. }
    51. return result;
    52. }
    53. void Serial_SendNum(uint32_t Num,uint8_t Length)
    54. {
    55. uint8_t i;
    56. for(i=0;i<Length;i++)
    57. {
    58. Serial_SendByte(Num/Serial_Pow(10,Length-i-1)%10+'0');//添加偏移得到对应字符
    59. }
    60. }
    61. //重定向到串口
    62. int fputc(int ch,FILE *f)
    63. {
    64. Serial_SendByte(ch);
    65. return ch;
    66. }
    67. /**
    68. * @brief
    69. * @param 参数1:格式化字符串 参数二:接受可变参数列表
    70. * @retval
    71. */
    72. void Serial_Printf(char *format,...)
    73. {
    74. char String[100];
    75. va_list arg; //定义一个参数列表变量
    76. va_start(arg,format);
    77. vsprintf(String,format,arg);
    78. va_end(arg);
    79. Serial_SendString(String);
    80. }

    串口发送+接收

    定义一个结构体变量但要分别调用    GPIO_Init(GPIOA,&GPIO_InitStructure);

    1. GPIO_InitTypeDef GPIO_InitStructure;
    2. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
    3. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
    4. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    5. GPIO_Init(GPIOA,&GPIO_InitStructure);
    6. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; 浮空输入或上拉输入
    7. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
    8. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    9. GPIO_Init(GPIOA,&GPIO_InitStructure);

    只支持1字节的接收

    1. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; 浮空输入或上拉输入
    2. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
    3. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    4. USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;

     1.查询模式

    1. if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET)//可读取
    2. {
    3. data=USART_ReceiveData(USART1);
    4. OLED_ShowHexNum(1,1,data,2);
    5. }

    2.中断模式

    初始化代码

    1. USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //开启到NVIC通道
    2. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    3. NVIC_InitTypeDef NVIC_InitStruct;
    4. NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;
    5. NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
    6. NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
    7. NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
    8. NVIC_Init(&NVIC_InitStruct);
    1. uint8_t Serial_GetRxFlag(void)
    2. {
    3. if(Serial_RxFlag==1)
    4. {
    5. Serial_RxFlag=0;
    6. return 1;
    7. }
    8. return 0;
    9. }
    10. uint8_t Serial_GetRxData(void)
    11. {
    12. return Serial_RxData;
    13. }
    14. void USART1_IRQHandler(void)
    15. {
    16. if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
    17. {
    18. Serial_RxData=USART_ReceiveData(USART1);
    19. Serial_RxFlag=1;
    20. USART_ClearITPendingBit(USART1,USART_IT_RXNE);
    21. }
    22. }

    主函数

    1. if (Serial_GetRxFlag() == 1)
    2. {
    3. RxData = Serial_GetRxData();
    4. Serial_SendByte(RxData);
    5. OLED_ShowHexNum(1, 8, RxData, 2);
    6. }

    串口收发HEX数据包

    在上述代码基础上根据状态图在中断里进行接收数据 存入Serial_RXPacket[];(固定包长)

    1. //状态机
    2. void USART1_IRQHandler(void)
    3. {
    4. static uint8_t s=0;
    5. static uint8_t pRXPacket=0;
    6. if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
    7. {
    8. uint16_t data=USART_ReceiveData(USART1);
    9. if(s==0)
    10. {
    11. if(data==0XFF)
    12. {
    13. s=1;
    14. pRXPacket=0;
    15. }
    16. }
    17. else if(s==1)
    18. {
    19. Serial_RXPacket[pRXPacket]=data;
    20. pRXPacket++;
    21. if(pRXPacket>=4)
    22. {
    23. s=2;
    24. }
    25. }
    26. else if(s==2)
    27. {
    28. if(data==0xFE)
    29. {
    30. s=0;
    31. Serial_RxFlag=1;
    32. }
    33. }
    34. USART_ClearITPendingBit(USART1,USART_IT_RXNE);
    35. }
    36. }
    37. //发送数据包
    38. void Serial_SendPacket(void)
    39. {
    40. Serial_SendByte(0xFF);
    41. Serial_SendArray(Serial_TXPacket,4);
    42. Serial_SendByte(0xFE);
    43. }

    串口收发文本数据包

    (可变包长)实现控制LED的亮灭

    发送部分可以sendstring或者直接打印

    1. //状态机
    2. void USART1_IRQHandler(void)
    3. {
    4. static uint8_t s=0;
    5. static uint8_t pRXPacket=0;
    6. if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
    7. {
    8. uint16_t data=USART_ReceiveData(USART1);
    9. if(s==0)
    10. {
    11. //主函数里完成操作后置0,所以当主函数完成后才进行接收下一个数据包
    12. if(data=='@'&& Serial_RxFlag == 0)
    13. {
    14. s=1;
    15. pRXPacket=0;
    16. }
    17. }
    18. else if(s==1)
    19. {
    20. if(data=='\r')
    21. {
    22. s=2;
    23. }
    24. else
    25. {
    26. Serial_RXPacket[pRXPacket]=data;
    27. pRXPacket++;
    28. }
    29. }
    30. else if(s==2)
    31. {
    32. if(data=='\n')
    33. {
    34. s=0;
    35. Serial_RXPacket[pRXPacket]='\0'; //字符串结束
    36. Serial_RxFlag=1;
    37. }
    38. }
    39. USART_ClearITPendingBit(USART1,USART_IT_RXNE);
    40. }
    41. }

    主函数

    1. while(1)
    2. {
    3. if(Serial_RxFlag==1) //收到完整的了,可以读出数据了
    4. {
    5. if(strcmp(Serial_RXPacket,"LED_ON")==0)
    6. {
    7. LED_ON(GPIO_Pin_1);
    8. Serial_SendString("LED_ON_OK\r\n");
    9. OLED_ShowString(1,1," ");
    10. OLED_ShowString(1,1,"LED_ON");
    11. }
    12. else if(strcmp(Serial_RXPacket,"LED_OFF")==0){
    13. LED_OFF(GPIO_Pin_1);
    14. Serial_SendString("LED_OFF_OK\r\n");
    15. OLED_ShowString(1,1," ");
    16. OLED_ShowString(1,1,"LED_OFF");
    17. }
    18. else{
    19. Serial_SendString("ERROR\r\n");
    20. OLED_ShowString(1,1," ");
    21. OLED_ShowString(1,1,"ERROR");
    22. }
    23. Serial_RxFlag=0;
    24. }
    25. }

  • 相关阅读:
    Java-Map常用子类
    【无标题】
    GitLab CI/CD关键词(十二):条件限定,only ,except,触发规则rules,工作流workflow
    公私域高效联动促进宠粮业务增长,Linkflow成功签约比瑞吉!
    Visual Studio现已支持 C++ 开发容器
    快慢指针实现-单链表的排序
    webpack5 PWA解决Web App 项目网络离线情况没法访问情况
    【Docker 内核详解】namespace 资源隔离(五):User namespaces
    【计算机毕业设计】7.健身俱乐部会籍管理系统+vue
    网页设计成品DW静态网页Html5响应式css3 (餐厅 6页 带轮播图)
  • 原文地址:https://blog.csdn.net/m0_70732442/article/details/130842705