cubemx串口的发送与接收_USART串口通信,中断方式,一分钟从菜鸟到大师(完整版)...

嵌入式系统中应用最广泛的一种通讯设备,只要三根线(TX,RX,GND),合适低速长距离通讯。发送和接收的控制流程如下:

1.初始化串口

包括使能串口时钟,使能发送和接收,定义引脚,波特率,数据位长度,奇偶校验方式,停止位位数。

使能串口模块接收中断,此时不能使能发送中断[炸弹]。

使能全局串口中断并设置优先级。

定义一个接收超时定时器,设置好超时值,并使能超时中断,这此定时器是关闭状态。

2. 发送

定义控制结构,

typedef struct txCtrl{ u8 buf[TX_SIZE],//根据最长发送帧定义大小 u8 idx; u8 len;//实际数据长度}txCtrl_t;txCtrl_t txCtrl;

2.1 数据准备

将发发送的数据装到txCtrl.buf,txCtrl.len=数据长度,txCtrl.idx=0。

2.2 启动发送

uartSend(){ //马上触发中断 使能发送缓冲器空中断;}

3. 接收

接收数据时会遇到一个问题,就是接到数据字节数是多少?一个帧数据接接收到什么时候才算结束?

解决这个问题,我们要使用到定时器。其原理是,接收到数据时,使能定时器,并设置超时时间为串口传输一个或几个字节的时间,注意,这个时间是随波特率变化的。如果定时器超时了,意味差这个帧结束了。

比如9600的波特率,起始位1,停止位1位,数据位8位,奇偶校验位0位,传输一个字节共10位的时间大约 10/9600=1ms.

定义控制结构,

typedef struct rxCtrl{ u8 buf[RX_SIZE],//根据最长接收帧定义大小 u8 len;//接收到的数据长度}rxCtrl_t;rxCtrl_t rxCtrl;

4. 中断服务

有两个中断服务要处理,一个是串口中断,一个是接收定时器超时中断。

串口中断void usartISR(void){ if( 发送结束中断标志==1 ) { 清除此标志 关闭发送结束中断功能 } if( txCtrl.len>0 )  { //把数据装入串口数据寄存器 DR = txCtrl.buf[txCtrl.idx++]; txCtrl.len--; //最后一个字节 if( txCtrl.len == 0 ) {  关闭发送缓冲器空中断,  使能发送结束中断功能 } }  //收到数据 if(接收数据缓冲器非空中断标志==1 ) { 使能并装填定时器的超时值 rxCtrl.buf[rxCtrl.len++] = RD; }  }接收定时器超时中断void timerOutISR(void){ Recevied = TRUE;//通知主程序处理}主程序if(Recevied){ 处理长度为rxCtrl.len的接收数据 //处理完要设置len为0 rxCtrl.len=0; Recevied=FALSE;}

注意⚠️,启动发送是使能发送缓冲器空中断,在发送最后一字节时关闭并使能发送完成中断,这样效率最高。也可以不用发送缓冲器空中断,都改用发送完成中断,但这样效率降低很多。

后面还会讲DMA方式,有什么不明白的,欢迎请留言。

码字很辛苦,谢谢转发与点赞。

02bd0f86afcc307043cc3c95aff1b1b1.gif

9DB针引脚定义

5bd0c698429e1f62a5f19dbd593a3513.png

串口数据帧示意

4665094dd46a0fd8038fb4371f9c7f2f.png

USB转接串口

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 在stm32cubemx中配置串口参数 首先,打开stm32cubemx软件,新建一个工程,选择需要使用的芯片型号,并进行初始化配置。 在Pinout & Configuration选项卡中,选择USART1,然后在右侧的Configuration栏中配置串口参数,如下图所示: ![image](https://user-images.githubusercontent.com/57706581/129364710-0b0ec9cd-7e6c-4e05-8d0c-6b7ee6e5c8b7.png) 其中,Baud Rate设置为115200,Data Bits为8,Stop Bits为1,Parity为None,Flow Control为None。 在Project Manager选项卡中,点击GENERATE CODE按钮生成代码。 2. 使用USART1串口,采用中断接收数据 在生成的代码中,找到main.c文件,在main函数中添加以下代码: ``` /* USER CODE BEGIN 2 */ HAL_UART_Receive_IT(&huart1, RxData, 1); /* USER CODE END 2 */ ``` 这段代码的作用是启动USART1串口中断接收功能,当接收到数据时,会触发中断,并执行中断处理函数。 在stm32cubeIDE中,中断处理函数的名称为USART1_IRQHandler,在stm32cubemx生成的代码中已经定义了该函数,我们只需要在该函数中添加处理接收数据的代码即可。 在USART1_IRQHandler函数中添加以下代码: ``` void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ if (__HAL_UART_GET_IT(&huart1, UART_IT_RXNE) != RESET) { uint8_t data; HAL_UART_Receive(&huart1, &data, 1, 0xFFFF); // 处理接收到的数据 } /* USER CODE END USART1_IRQn 1 */ } ``` 其中,__HAL_UART_GET_IT函数用于判断是否接收到了数据,如果接收到了数据,则调用HAL_UART_Receive函数接收数据,并进行处理。 3. 使用DMA方式发送数据 在stm32cubemx生成的代码中,已经默认启用了DMA方式发送数据,我们只需要在main函数中添加以下代码即可: ``` /* USER CODE BEGIN 4 */ uint8_t TxData[] = "Hello World!\r\n"; HAL_UART_Transmit_DMA(&huart1, TxData, sizeof(TxData)); /* USER CODE END 4 */ ``` 这段代码的作用是启动USART1串口的DMA发送功能,将TxData数组中的数据发送出去。 至此,我们已经完成了使用USART1串口,采用中断接收数据,使用DMA方式发送数据的配置代码。完整代码如下: ``` #include "main.h" #include "stm32f1xx_hal.h" #include "usart.h" #include "gpio.h" uint8_t RxData[1]; void SystemClock_Config(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ HAL_UART_Receive_IT(&huart1, RxData, 1); uint8_t TxData[] = "Hello World!\r\n"; HAL_UART_Transmit_DMA(&huart1, TxData, sizeof(TxData)); /* USER CODE END 2 */ while (1) { } } void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ if (__HAL_UART_GET_IT(&huart1, UART_IT_RXNE) != RESET) { uint8_t data; HAL_UART_Receive(&huart1, &data, 1, 0xFFFF); // 处理接收到的数据 } /* USER CODE END USART1_IRQn 1 */ } void Error_Handler(void) { } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值