Ultra-simple GPIO simulation realizes variable baud rate asynchronous serial port transceiver (STM32)

 First, use a logic analyzer to view the ch340 serial port data waveform, and then write the receiving logic according to the waveform.

The start bit and stop bit are both fixed forms

Use an external interrupt to capture the data start bit, turn off the interrupt, then clear the timer count and restart the timer, sample the data every 1/baud rate s, and then shift it into a byte to turn on the interrupt and enter the next waiting state (lower bit first ) receive )

uint8_t rec_count=0,rec_data[20]={0},rec_i=0,rx_temp;
#define baud 9600//接收波特率
int timer_rx=1000000/baud;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	HAL_GPIO_WritePin(led_GPIO_Port,led_Pin,0);
	HAL_NVIC_DisableIRQ(EXTI15_10_IRQn);//关闭外部中断
	rec_i=0;//接收位标记
	rx_temp=0;//临时接收数据
	htim1.Instance->CNT=0;//清零定时器计数值
	while(htim1.Instance->CNT<timer_rx*9){//取8位数据位+1停止,无奇偶校验+1起始位
		if(htim1.Instance->CNT>timer_rx*rec_i+(timer_rx+timer_rx/4)&&rec_i<8){//定时采样查看数据
			rx_temp=rx_temp|((HAL_GPIO_ReadPin(rx_GPIO_Port,rx_Pin)&1)<<rec_i);//数据移位整合(默认低位先发送)
			rec_i++;
		}
	}
	rec_data[rec_count]=rx_temp;//存储临时值
	rec_count++;
	while(/*HAL_GPIO_ReadPin(rx_GPIO_Port,rx_Pin)==1*/htim1.Instance->CNT<timer_rx*10);//等待(前面等待时间不够)
	__HAL_GPIO_EXTI_CLEAR_IT(rx_Pin);
	HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);//开启接收中断,等待下一次
	HAL_GPIO_WritePin(led_GPIO_Port,led_Pin,1);

}

Sending is simpler. You only need to send one bit of data every 1/baud rate s after sending the start bit ( the low bit is sent first ), and finally send the stop bit.

void self_uart_send(int bauds,uint8_t *s){
	int timer_tx=1000000/bauds;//给波特率(<9600)计算定时器计数比较值(9600->104us即1000000/9600)
	HAL_NVIC_DisableIRQ(EXTI15_10_IRQn);//关闭接收
	while(*s){
		rec_i=0;//发送位清零
		HAL_GPIO_WritePin(tx_GPIO_Port,tx_Pin,0);//起始位
		htim1.Instance->CNT=0;//计时清零
		while(htim1.Instance->CNT<timer_tx);//一个bit(start)
		while(htim1.Instance->CNT<timer_tx*11 ){//8个数据+1个起始+2停止
			if(htim1.Instance->CNT>(timer_tx*rec_i+timer_tx)&&rec_i<8||rec_i==0){
					HAL_GPIO_WritePin(tx_GPIO_Port,tx_Pin,(*s>>rec_i)&1);//低位先发送
				rec_i++;
			} 
			if(htim1.Instance->CNT>timer_tx*9)HAL_GPIO_WritePin(tx_GPIO_Port,tx_Pin,1);//停止位
			
		}
		while(htim1.Instance->CNT<timer_tx*12);//直到停止位结束
		s++;//
	}
	HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);//开启接收
	
}

Note that to use the timer, you need to enable it first

	HAL_TIM_Base_Start(&htim1);

Code: https://gitee.com/caneve/opencaneve/tree/main/STM32/103c8analog_uart

Demonstration video: Super simple STM32 uses GPIO analog serial port to implement sending and receiving_bilibili_bilibili

Guess you like

Origin blog.csdn.net/hhcgn/article/details/131570616