当前位置:   article > 正文

STM32串口通信+数据处理_如何通过串口通信改stm32中的值

如何通过串口通信改stm32中的值

一、初始化设置

配置能够输出、接收串口数据(ttl信号)的GPIO口,下方链接中有对应uart配置的引脚图。STM32F103X芯片PWM应用_tim_ocmode_pwm2-CSDN博客

这里我选用的是USART1。

  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  2. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  3. GPIO_InitTypeDef GPIO_InitStructure;
  4. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  5. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  6. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  7. GPIO_Init(GPIOA, &GPIO_InitStructure);
  8. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  9. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  10. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11. GPIO_Init(GPIOA, &GPIO_InitStructure);
  12. USART_InitTypeDef USART_InitStructure;
  13. USART_InitStructure.USART_BaudRate = 9600;
  14. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  15. USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
  16. USART_InitStructure.USART_Parity = USART_Parity_No;
  17. USART_InitStructure.USART_StopBits = USART_StopBits_1;
  18. USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  19. USART_Init(USART1, &USART_InitStructure);
  20. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  21. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  22. NVIC_InitTypeDef NVIC_InitStructure;
  23. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  24. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  25. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  26. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  27. NVIC_Init(&NVIC_InitStructure);
  28. USART_Cmd(USART1, ENABLE);

以上这段代码网上很多,其中含义大家自己去了解,我在此不多做介绍。

二、发送数据

  1. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  2. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

在初始化时,我们设定了PA9是发送口(口),而在串口中高电平是1,低电平是0,(stm32的串口信号属于ttl,还有什么rs232,ch340这些串口类型,我下篇文章再介绍)所以配置是AF(浮空)状态不确定,防止误发信号,至于为什么是pp(推免:能输出一定电流)因为要驱动你外接设备的串口。

  1. USART_SendData(USART1, Byte);
  2. while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

第一行代码参数是发送数据的串口,和发送的数据(只要是8位就行,16位,32位它会只取低8位),第二行是循环检测标志位,直到数据发送完毕。

根据这个发送数据的原理,可以自行构造函数,发送文本,字符串或者数字。

三、接受数据

  1. void USART1_IRQHandler(void)//串口中断
  2. {
  3. if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)//为1则没有读取完
  4. {
  5. RS232_RxData = USART_ReceiveData(USART1);//将读取的值赋给变量
  6. RS232_RxFlag = 1;
  7. USART_ClearITPendingBit(USART1, USART_IT_RXNE);
  8. }
  9. }

该中断函数会在有数据返回时,自动开启,读取标志位如果置零,我们将读取完的数据赋给变量,RS232_RxData,且我们手动添加一个标志位RS232_RxFlag置一,并再次构建俩个函数,用来保存RS232_RxData,RS232_RxFlag中的数据,因为这俩个变量在设计时就充当了中间变量的角色。

  1. uint8_t RS232_GetRxFlag(void)
  2. {
  3. if (RS232_RxFlag == 1)
  4. {
  5. RS232_RxFlag = 0;
  6. return 1;
  7. }
  8. return 0;
  9. }
  10. uint8_t RS232_GetRxData(void)
  11. {
  12. return RS232_RxData;
  13. }

最底层的8位数据我们已经可以拿到了,接下来开始缓存。

  1. uint8_t Rx_Buffer[BUFFER_SIZE];//数据缓存的数组
  2. uint32_t Rx_Index = 0;//缓存算法中的检索值
  1. #define BUFFER_SIZE 100 //服务器发送数据的最大缓存数
  2. #define RESPONSE_SIZE 8 //服务器与单片机数据交换的指定数据长度
  3. #define HC_MODE 1
  4. #define RS232_MODE 2
  5. #define TTS_MODE 3
  1. /*数据缓存*/
  2. uint8_t* Data_Caching(uint8_t SERIAL_MODE)
  3. {
  4. while(1)
  5. {
  6. //缓存开始
  7. if(GetRxFlag(SERIAL_MODE)==1)
  8. {
  9. Rx_Buffer[Rx_Index] = GetRxData(SERIAL_MODE);
  10. Rx_Index=(Rx_Index+1)%BUFFER_SIZE;
  11. }
  12. //缓存结束
  13. if(Rx_Buffer[Rx_Index-1]==0xf4)
  14. {
  15. return getSubArray(Rx_Buffer,0,Rx_Index);//返回缓存片段,后续将缓存清空
  16. }
  17. }
  18. }

这是我从我一个项目里摘抄的因为里面有三个串口,不要直接拿来用,SERIAL_MODE,你们要用这个函数的时候填2或RS232_MODE就行。参考这段代码

  1. uint8_t GetRxFlag(uint8_t SERIAL_MODE)
  2. {
  3. switch(SERIAL_MODE)
  4. {
  5. case 1:
  6. return HC_GetRxFlag();
  7. break;
  8. case 2:
  9. return RS232_GetRxFlag();
  10. break;
  11. case 3:
  12. return TTS_GetRxFlag();
  13. break;
  14. }
  15. }
  16. uint8_t GetRxData(uint8_t SERIAL_MODE)
  17. {
  18. switch(SERIAL_MODE)
  19. {
  20. case 1:
  21. return HC_GetRxData();
  22. break;
  23. case 2:
  24. return RS232_GetRxData();
  25. break;
  26. case 3:
  27. return TTS_GetRxData();
  28. break;
  29. }
  30. }

这里我设置最大能缓存100个字节,然后在缓存字节中有出现0xf4这个字节(这是我的需求你们也可以进行更改),缓存结束,然后我们截取0xf4之前的所有数据,组成一个数据片段。

  1. /*结合数据缓存,将片段截取出去*/
  2. uint8_t* getSubArray(uint8_t arr[], int start, int end)
  3. {
  4. int subArrayLength = end - start + 1;
  5. uint8_t* subArray = (uint8_t*)malloc(subArrayLength * sizeof(uint8_t));
  6. for (int i = 0; i < subArrayLength; i++) {
  7. subArray[i] = arr[start + i];
  8. }
  9. return subArray;
  10. }

将参数带入这个函数,三个参数分别是,截取数据的数组,起,始位置。

这样我们就完成了对数据的缓存,和数据截取,接下来是数据比对。

  1. /*数据比对*/
  2. uint8_t Data_Comparison(uint8_t *str1,uint8_t *str2)
  3. {
  4. if(Rx_Index==RESPONSE_SIZE)
  5. {
  6. for(int index=0;index<RESPONSE_SIZE;index++)
  7. {
  8. if(str1[index]!=str2[index])
  9. {
  10. return 0x00;
  11. }
  12. }
  13. return 0x01;
  14. }
  15. else
  16. {
  17. return 0x00;
  18. }
  19. }

str1是你缓存的数据,str2是你任务需求自己设定的一个数据,如果返回数据中存在你预期设定的数据返回0x01,若没有则返回0x00。数据比对完后,别忘了清空缓存。

  1. /*数据清空*/
  2. void Data_Cleared()
  3. {
  4. for(int index=0;index<Rx_Index;index++)
  5. {
  6. Rx_Buffer[index]=0x00;
  7. }
  8. Rx_Index=0;
  9. }

以上我主要是介绍一个思路,部分代码是通用的。

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

闽ICP备14008679号