赞
踩
配置能够输出、接收串口数据(ttl信号)的GPIO口,下方链接中有对应uart配置的引脚图。STM32F103X芯片PWM应用_tim_ocmode_pwm2-CSDN博客
这里我选用的是USART1。
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
-
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
- USART_InitTypeDef USART_InitStructure;
- USART_InitStructure.USART_BaudRate = 9600;
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
- USART_InitStructure.USART_Parity = USART_Parity_No;
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- USART_Init(USART1, &USART_InitStructure);
-
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
-
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
-
- NVIC_InitTypeDef NVIC_InitStructure;
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
- NVIC_Init(&NVIC_InitStructure);
-
- USART_Cmd(USART1, ENABLE);
以上这段代码网上很多,其中含义大家自己去了解,我在此不多做介绍。
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
在初始化时,我们设定了PA9是发送口(口),而在串口中高电平是1,低电平是0,(stm32的串口信号属于ttl,还有什么rs232,ch340这些串口类型,我下篇文章再介绍)所以配置是AF(浮空)状态不确定,防止误发信号,至于为什么是pp(推免:能输出一定电流)因为要驱动你外接设备的串口。
- USART_SendData(USART1, Byte);
- while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
第一行代码参数是发送数据的串口,和发送的数据(只要是8位就行,16位,32位它会只取低8位),第二行是循环检测标志位,直到数据发送完毕。
根据这个发送数据的原理,可以自行构造函数,发送文本,字符串或者数字。
- void USART1_IRQHandler(void)//串口中断
- {
- if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)//为1则没有读取完
- {
- RS232_RxData = USART_ReceiveData(USART1);//将读取的值赋给变量
- RS232_RxFlag = 1;
- USART_ClearITPendingBit(USART1, USART_IT_RXNE);
- }
- }
该中断函数会在有数据返回时,自动开启,读取标志位如果置零,我们将读取完的数据赋给变量,RS232_RxData,且我们手动添加一个标志位RS232_RxFlag置一,并再次构建俩个函数,用来保存RS232_RxData,RS232_RxFlag中的数据,因为这俩个变量在设计时就充当了中间变量的角色。
- uint8_t RS232_GetRxFlag(void)
- {
- if (RS232_RxFlag == 1)
- {
- RS232_RxFlag = 0;
- return 1;
- }
- return 0;
- }
-
- uint8_t RS232_GetRxData(void)
- {
- return RS232_RxData;
- }
最底层的8位数据我们已经可以拿到了,接下来开始缓存。
- uint8_t Rx_Buffer[BUFFER_SIZE];//数据缓存的数组
- uint32_t Rx_Index = 0;//缓存算法中的检索值
- #define BUFFER_SIZE 100 //服务器发送数据的最大缓存数
- #define RESPONSE_SIZE 8 //服务器与单片机数据交换的指定数据长度
-
- #define HC_MODE 1
- #define RS232_MODE 2
- #define TTS_MODE 3
- /*数据缓存*/
- uint8_t* Data_Caching(uint8_t SERIAL_MODE)
- {
- while(1)
- {
- //缓存开始
- if(GetRxFlag(SERIAL_MODE)==1)
- {
- Rx_Buffer[Rx_Index] = GetRxData(SERIAL_MODE);
- Rx_Index=(Rx_Index+1)%BUFFER_SIZE;
- }
- //缓存结束
- if(Rx_Buffer[Rx_Index-1]==0xf4)
- {
- return getSubArray(Rx_Buffer,0,Rx_Index);//返回缓存片段,后续将缓存清空
- }
- }
- }
这是我从我一个项目里摘抄的因为里面有三个串口,不要直接拿来用,SERIAL_MODE,你们要用这个函数的时候填2或RS232_MODE就行。参考这段代码
- uint8_t GetRxFlag(uint8_t SERIAL_MODE)
- {
- switch(SERIAL_MODE)
- {
- case 1:
- return HC_GetRxFlag();
- break;
- case 2:
- return RS232_GetRxFlag();
- break;
- case 3:
- return TTS_GetRxFlag();
- break;
- }
- }
-
- uint8_t GetRxData(uint8_t SERIAL_MODE)
- {
- switch(SERIAL_MODE)
- {
- case 1:
- return HC_GetRxData();
- break;
- case 2:
- return RS232_GetRxData();
- break;
- case 3:
- return TTS_GetRxData();
- break;
- }
- }
这里我设置最大能缓存100个字节,然后在缓存字节中有出现0xf4这个字节(这是我的需求你们也可以进行更改),缓存结束,然后我们截取0xf4之前的所有数据,组成一个数据片段。
- /*结合数据缓存,将片段截取出去*/
- uint8_t* getSubArray(uint8_t arr[], int start, int end)
- {
- int subArrayLength = end - start + 1;
- uint8_t* subArray = (uint8_t*)malloc(subArrayLength * sizeof(uint8_t));
-
- for (int i = 0; i < subArrayLength; i++) {
- subArray[i] = arr[start + i];
- }
-
- return subArray;
- }
将参数带入这个函数,三个参数分别是,截取数据的数组,起,始位置。
这样我们就完成了对数据的缓存,和数据截取,接下来是数据比对。
- /*数据比对*/
- uint8_t Data_Comparison(uint8_t *str1,uint8_t *str2)
- {
- if(Rx_Index==RESPONSE_SIZE)
- {
- for(int index=0;index<RESPONSE_SIZE;index++)
- {
- if(str1[index]!=str2[index])
- {
- return 0x00;
- }
- }
- return 0x01;
- }
- else
- {
- return 0x00;
- }
-
- }
str1是你缓存的数据,str2是你任务需求自己设定的一个数据,如果返回数据中存在你预期设定的数据返回0x01,若没有则返回0x00。数据比对完后,别忘了清空缓存。
- /*数据清空*/
- void Data_Cleared()
- {
- for(int index=0;index<Rx_Index;index++)
- {
- Rx_Buffer[index]=0x00;
- }
- Rx_Index=0;
- }
以上我主要是介绍一个思路,部分代码是通用的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。