1、硬件连接
本文使用串口0,对应的引脚为PA9和PA10。
2、GPIO复用功能
可以看出,复用功能为AF7。
3、实现思路
利用串口接收相邻两个字符的时间来判断一串数据是否接收完成,如果超过设定的时间,还没有接收到下一个字符,则认为一串数据接收完成。
如果使用115200波特率,数据长度为8bit,停止位为1bit,那么接收一个字节大约需要,(1/115200)9=0.78ms。
那么就可以利用,接收完一个字符后,如果0.78ms之内没有下一个数据,那么就可以认为一串数据接收完成,考虑到单片机接收数据保存,这里设定超时时间为5ms。
4、核心代码
主要是利用串口接收中断和应用层超时。
代码语言:javascript复制#define UART_MAX_LEN 200
struct
{
uint8_t Timeout;
uint8_t RecvBuff[UART_MAX_LEN];
uint8_t RecvLen;
} SerialStr;
void SerialInit(void)
{
/* enable COM GPIO clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* enable USART clock */
rcu_periph_clock_enable(RCU_USART0);
/* connect port to USART TX */
gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);
/* connect port to USART RX */
gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);
/* configure USART TX as alternate function push-pull */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_10);
/* configure USART RX as alternate function push-pull */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_10);
nvic_irq_enable(USART0_IRQn, 1);
/* USART configure */
usart_deinit(USART0);
usart_word_length_set(USART0, USART_WL_8BIT);
usart_stop_bit_set(USART0, USART_STB_1BIT);
usart_parity_config(USART0, USART_PM_NONE);
usart_baudrate_set(USART0, 115200U);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_enable(USART0);
usart_interrupt_enable(USART0, USART_INT_RBNE);
}
void SerialRecvTimeout(void)
{
if(SerialStr.Timeout>0)
{
SerialStr.Timeout--;
}
}
void SerialRecv(uint8_t data)
{
SerialStr.Timeout=5;
if(SerialStr.RecvLen<UART_MAX_LEN)
{
SerialStr.RecvBuff[SerialStr.RecvLen ]=data;
}
}
void SerialSend(uint8_t *data,uint8_t len)
{
for(uint8_t i=0; i<len;i )
{
//while (RESET == usart_flag_get(USART1, USART_FLAG_TBE));
while (RESET == usart_flag_get(USART0, USART_FLAG_TC));
usart_data_transmit(USART0, data[i]);
}
}
void SerialPro(void)
{
if(!SerialStr.Timeout&&SerialStr.RecvLen)
{
printf("Recv:%d,[",SerialStr.RecvLen);
#if 1
SerialSend(SerialStr.RecvBuff,SerialStr.RecvLen);
#else
for(uint8_t i=0;i<SerialStr.RecvLen;i )
{
printf(" d",SerialStr.RecvBuff[i]);
}
#endif
printf("]rn");
SerialStr.RecvLen=0;
}
}
void USART0_IRQHandler(void)
{
if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE))
{
SerialRecv(usart_data_receive(USART0));
}
}