计算机系统应用教程网站

网站首页 > 技术文章 正文

基于标准库STM32单片机中的串口使用

btikc 2024-10-12 11:45:04 技术文章 5 ℃ 0 评论

一、STM32标准库串口驱动

相对于其他通信,串口通信还是比较简单的。对于单片机来说,就是有2个管脚,一个是tx ,一个为rx 。但只有这2个管脚是不能够来通信的,需要进行必要的寄存器配置,使能串口功能。然后才可以进行通信操作。

stm32f407这款单片机中有6个串口可供使用。

相关的驱动代码:

管理gpio初始化

		GPIO_InitTypeDef GPIO_InitStructure;
		RCC_AHB1PeriphClockCmd(uart_gpio->gpio_uart_clock,ENABLE); 
		GPIO_PinAFConfig(uart_gpio->gpio_group,uart_gpio->gpio_pin_source_rx,uart_gpio->gpio_af_uart); 
		GPIO_PinAFConfig(uart_gpio->gpio_group,uart_gpio->gpio_pin_source_tx,uart_gpio->gpio_af_uart);
		GPIO_InitStructure.GPIO_Pin = uart_gpio->gpio_rx | uart_gpio->gpio_tx;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
		GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
		GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
		GPIO_Init(uart_gpio->gpio_group,&GPIO_InitStructure);

中断nvic配置:

NVIC_InitTypeDef NVIC_InitStructure;
		NVIC_InitStructure.NVIC_IRQChannel=uart_nvic->uart_irq_channel ;
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=uart_nvic->uart_irq_pp; 
		NVIC_InitStructure.NVIC_IRQChannelSubPriority=uart_nvic->uart_irq_subp;
		NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
		NVIC_Init(&NVIC_InitStructure);

串口参数配置功能:

USART_InitStructure.USART_BaudRate = uart_config->baudrate;
		USART_InitStructure.USART_WordLength = uart_config->uart_word_length;
		USART_InitStructure.USART_StopBits = uart_config->uart_stop_bits;
		USART_InitStructure.USART_Parity = uart_config->uart_parity;
		USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
		USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	
		USART_Init(uart_config->uart, &USART_InitStructure);  

因为stm32中有多个串口可以使用,方便代码重用,所以将一些参数利用结构体做成一个数据结构,统一配置。

相关的结构体配置代码如下:

typedef struct
{
	uint8_t uart_irq_channel; //串口中断号
	uint8_t uart_irq_pp;      //中断优先级,主优先级
	uint8_t uart_irq_subp;    //中断优先级,子优先级
}	uart_nvic_t;

typedef struct
{
	uint32_t gpio_uart_clock;        //串口GPIO时钟
	GPIO_TypeDef* gpio_group;   //所属组
	uint16_t gpio_tx;           //收发数据口
	uint16_t gpio_rx;
	uint8_t gpio_pin_source_tx;   //复用收发配置
	uint8_t gpio_pin_source_rx;
	uint8_t  gpio_af_uart;         //gpio uart复用
}uart_gpio_t;


typedef struct
{
	USART_TypeDef * uart;  
	uint32_t uart_clock;   //串口时钟
	uint32_t baudrate;     //波特率
	uint16_t uart_word_length; //数据长度
  uint16_t uart_stop_bits;   //停止位          
  uint16_t uart_parity;      //校验
}uart_config_t;

typedef struct
{
	uint32_t dma_clock;
	DMA_Stream_TypeDef * tx_stream_type;
	uint32_t tx_dma_channel;
	uint32_t tx_dma_peripheral_base_addr;
	uint32_t tx_memory_base_addr;
	uint32_t tx_dma_idr;
	uint32_t tx_buffer_size;
	uint8_t * tx_buffer; //指向发送数据缓冲区
	
	DMA_Stream_TypeDef * rx_stream_type;
	uint32_t rx_dma_channel;
	uint32_t rx_dma_peripheral_base_addr;
	uint32_t rx_memory_base_addr;
	uint32_t rx_dma_idr;
	uint32_t rx_buffer_size;
	
}uart_dma_t;

二、利用中断进行数据读取

例如:利用串口1中断来读取串口数据

void USART1_IRQHandler(void)
{
	if(USART_GetITStatus(debug_uart_config.uart, USART_IT_RXNE) != RESET)                 //判断发生接收中断
  {
		uint8_t recv = USART_ReceiveData(debug_uart_config.uart)&0xFF;   
		//USART_ClearITPendingBit(USART1,   USART_IT_RXNE);                 //清除中断标志
		ring_buffer_2048_write_char(&usart1_ring_buffer,recv);
		if(recv==0x0D)
		{
			recv0d=1;
		}
		if(recv == 0x0A && recv0d==1)
		{
			recv0d=0;
			recv_comp= 1;
		}
		//debug_data(recv);
	}
	if(USART_GetITStatus(debug_uart_config.uart, USART_IT_TXE) != RESET)                  
  { 
		USART_ITConfig(debug_uart_config.uart, USART_IT_TXE, DISABLE);                     
  }
}

首先判断是否发生接收中断,如果是接收中断则读取一个字符,将读取到的字符写入到循环缓冲区中。

上述代码中,做拉“\r\n”作为结束标识的判断。当接收数据以“\r\n”时,说明已经接收完成,就可以进行数据的操作拉。

三、串口数据的发送

串口配置完成后,就可以进行数据发送。

相关代码如下所示:

void uart_send_data(USART_TypeDef* uart,uint8_t data)
{
 
	USART_SendData(uart, data);         //向串口发送数据
	while(USART_GetFlagStatus(uart,USART_FLAG_TC)!=SET);//等待发送结束
}

串口接收数据图:




本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表