3.串口USART标准固件库发送与中断接收解析

1.描述

串口通信常见于MCU之间以及MCU与高速上位机等场景,用于传输数据。

2.串口设置

2.1.串口GPIO初始化和引脚复用

/* USART0 Initialize*/
nvic_irq_enable(USART0_IRQn, 0, 0);
rcu_periph_clock_enable(RCU_GPIOB);	/* enable GPIO clock */
rcu_periph_clock_enable(RCU_USART0);	/* enable USART clock */
gpio_af_set(GPIOB, GPIO_AF_7, GPIO_PIN_6);	/* connect port to USARTx_Tx */
gpio_af_set(GPIOB, GPIO_AF_7, GPIO_PIN_7);	/* connect port to USARTx_Rx */
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_6);	/* configure USART Tx as alternate function push-pull */
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_7);	/* configure USART Rx as alternate function push-pull */
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_7);
/* USART2 Initialize*/
 nvic_irq_enable(USART2_IRQn, 0, 0);
 rcu_periph_clock_enable(RCU_GPIOC);	/* enable GPIO clock */
 rcu_periph_clock_enable(RCU_USART2);	/* enable USART clock */
 gpio_af_set(GPIOC, GPIO_AF_7, GPIO_PIN_10);	/* connect port to USARTx_Tx */
 gpio_af_set(GPIOC, GPIO_AF_7, GPIO_PIN_11);	/* connect port to USARTx_Rx */
 gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10);	/* configure USART Tx as alternate function push-pull */
 gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);
 gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_11);	/* configure USART Rx as alternate function push-pull */
 gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_11);

2.1.串口的波特率、停止位等与USART的中断服务在NVIC使能

/* USART0 configure */
usart_deinit(USART0);
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);
 /* USART2 configure */
 usart_deinit(USART2);
 usart_baudrate_set(USART2,115200U);
 usart_receive_config(USART2, USART_RECEIVE_ENABLE);
 usart_transmit_config(USART2, USART_TRANSMIT_ENABLE);
 usart_enable(USART2);
 usart_interrupt_enable(USART2, USART_INT_RBNE);

3.串口发送

  • 输入参数:usartx、发送字节串、字节长度。
  • 返回参数:发送字节的长度。
uint16_t uart_send_bytes(uint32_t usart_periph, uint8_t *data, uint16_t len)
{
		uint8_t i;
		for(i = 0; i < len; i++) 
		{
				while(usart_flag_get(usart_periph, USART_FLAG_TC) == RESET);      
				usart_data_transmit(usart_periph, data[i]);
		}
		while(usart_flag_get(usart_periph, USART_FLAG_TC) == RESET);
		return len;
}

4.串口中断接收

  • 串口中断使能于接收缓冲区非空中断标志位。
usart_interrupt_enable(USART2, USART_INT_RBNE);
void USART0_IRQHandler(void)
{
		if(usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE) != RESET)
		{
				usart_interrupt_flag_clear(USART0,USART_INT_FLAG_RBNE);
				

				Uart0_RecvBuffer[Uart0_RecvLenth] = usart_data_receive(USART0);
				Uart0_RecvLenth ++;
				if(Uart0_RecvLenth == 1)
					Uart0_RecvLenth = 0;

				
		}
}

5.基础应用案例

  • 此应用案例的使用场景为上位机成功实现人脸识别后发送信令给下位机,下位机对灯进行点亮(用于替代开门功能)。
  • 此应用案例将展现串口普通发送、串口中断接收,其他内容将省略。
  • 串口初始化将被省略。
uint8_t flag = 0;
//串口数据接收缓存
uint8_t   USART0_RecvBuffer[8];
uint8_t   USART0_buf[8];
uint16_t  USART0_RecvLenth = 0;

uint8_t callback_order[4] = {0x4F, 0x4B, 0x0D, 0x0A};

void process(void)
{
	memset(USART0_RecvBuffer, 0, 8);//清空缓冲变量
	if(USART0_RecvBuffer[0] == 'S')
	{
		if(USART0_RecvBuffer[7] == 'E')
		{
			if(USART0_RecvBuffer[1] == '1')
				LED_ON();
			if(USART0_RecvBuffer[1] == '2')
				LED_OFF();
		}
	}
	delay(500);
}

void USART0_IRQHandler(void)
{
		if(usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE) != RESET)//接收缓冲区非空(用于判断是否接收到数据)
		{
			usart_interrupt_flag_clear(USART0,USART_INT_FLAG_RBNE);
			
			USART0_RecvBuffer[USART0_RecvLenth] = usart_data_receive(USART0);
			if (USART0_RecvBuffer[0] == 'S')//开始位
			{
				flag = 1;
			}
			
			if (flag == 1)
				USART0_RecvLenth ++;
			
			if (USART0_RecvBuffer[7] == 'E')//数据结束位
			{
				flag = 0;
				//判断区域
				process();
				delay(500);
				//结束时清空索引、标志位、接收变量
				memset(USART0_RecvBuffer, 0, 8);
				USART0_RecvLenth = 0;		
				uart_send_bytes(USART0, callback_order, 4);
			}	
			if (USART0_RecvLenth >= 7)
				USART0_RecvLenth = 0;
		}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
好的,下面是使用标准和DMA实现USART中断接收发送的步骤: 1. 配置USART的GPIO引脚和时钟,以及NVIC中断优先级。 2. 配置USART的相关参数,包括波特率、数据位、停止位等。 3. 配置USART中断,包括接收中断发送中断。 4. 配置DMA,包括DMA通道、传输方向、传输数据长度和存储器地址等。 5. 在中断函数中,根据接收发送的状态进行相应的处理。 下面是示例代码: ```c #include "stm32f10x.h" /* USART1 GPIO 配置,PA9为USART1的TX引脚,PA10为USART1的RX引脚 */ GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; DMA_InitTypeDef DMA_InitStructure; /* 接收缓冲区 */ uint8_t rxBuffer[100]; int main(void) { /* 配置USART1的GPIO引脚和时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* 配置USART1的时钟和参数 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); /* 配置USART1的中断 */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* 配置DMA */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA1_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)rxBuffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = sizeof(rxBuffer); DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5, &DMA_InitStructure); DMA_Cmd(DMA1_Channel5, ENABLE); /* 开启USART1 */ USART_Cmd(USART1, ENABLE); while (1) { /* 发送数据 */ USART_SendData(USART1, 'A'); while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); /* 等待接收完成 */ while (DMA_GetFlagStatus(DMA1_FLAG_TC5) == RESET); DMA_ClearFlag(DMA1_FLAG_TC5); } } void USART1_IRQHandler(void) { /* 接收中断 */ if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { USART_ClearITPendingBit(USART1, USART_IT_RXNE); } } ``` 以上代码实现了USART中断接收发送,其中接收使用了DMA,可以实现接收到一定长度的数据后自动触发中断。需要注意的是,以上代码只是示例,具体的实现过程需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AzusaFighting

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值