上期我们使用GPIO模拟串口成功的发送了数据,本期我们进一步实现串口接收的功能。
首先,因为波特率的统一,我们可以使用同一个定时器来接收和发送。
这里我们定义两个变量来设置发送和接收的标记。
其次,由于起始位是一个低电平,空闲状态的串口总线是高电平,因此当我们收到消息的时候,实际上是一个下降沿。
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ if(RXFlag==0) { RXFlag = 1; Recive = 0; }}
因此我们将RX引脚设置为下降沿的外部中断,并且收到外部中断,并且如果RX空闲(RXFlag ==
0)的话,就将接收缓存区(Recive)置零,之后将RX标志位置1,在定时器中可以处理。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if(TXFlag==1) { HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,Data[num++]); if(num == 10) { num = 0; HAL_TIM_Base_Stop_IT(&htim1);//关闭定时器 TXFlag = 0; } } /* 外部中断触发后接收信息 */ if(RXFlag==1) { num++; if(num>=1&&num<=8) { /* 从第二位开始总计八位,对应数据从低到高 */ Recive = Recive|(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_10)<<(num-1)); }
if(num == 10) { num = 0; RXFlag = 0; } } }
定时器的中断回调函数中,我们逐一读取数据的低位到高位,将其存入缓存区Recive中。
之后我们运行代码,Debug代码,利用串口助手发送数据,查看Recive的数据是否为我们发送的数据。
我们在设置一个接收完成的标志,当接收完成的时候,就将我们的数据利用上期我们模拟发送的代码发送回来。
可以实现接收和发送。 但是接收和发送的乱码率还是比较高的。
这可能是由于共用一个定时器的原因,导致接收的数据出现了异常。 主要代码
/* USER CODE BEGIN 4 */int TXnum = 0;int RXnum = 0;void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if(TXFlag==1) { HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,Data[TXnum++]); if(TXnum == 10) { TXnum = 0; TXFlag = 0; TXSTA = 1; } } /* 外部中断触发后接收信息 */ if(RXFlag==1) { if(RXnum>=1&&RXnum<=8) { /* 从第二位开始总计八位,对应数据从低到高 */ Recive = Recive|(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_10)<<(RXnum-1)); } RXnum++; if(RXnum == 10) { RXnum = 0; RXFlag = 0; RXSTA = 1; } } }
/* 中断回调函数 */void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ if(RXFlag==0) { RXFlag = 1; Recive = 0; RXSTA = 0; }}
/* Private includes ----------------------------------------------------------*//* USER CODE BEGIN Includes */#include <stdio.h>int Data[10];int RXFlag = 0;int TXFlag = 0;int RXSTA = 0;int TXSTA = 1;unsigned char Recive = 0;/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*//* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*//* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*//* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */void MyPrintf(int s);/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/void SystemClock_Config(void);/* USER CODE BEGIN PFP */void MyPrintf(int s){ if(TXFlag==0 && TXSTA) { Data[0] = 0; for(unsigned char i = 0;i<8;i++) { if(s & 0x01){ Data[i+1] = 1; } else{ Data[i+1] = 0; } s = s >> 1; } Data[9] = 1; TXFlag = 1; TXSTA = 0; }}
int fputc(int ch, FILE *f) { // 发送单个字符 MyPrintf(ch); // 返回发送的字符 return ch;}