蓝桥杯嵌入式学习笔记(5):UART程序设计

文章介绍了如何在STM32G4开发板上实现异步串口通信,包括同步与异步通信的区别、CubeMX的配置步骤、代码编程(如初始化、中断处理和发送/接收函数)、以及系统时钟设置。通过LED灯控制验证了串口通信的收发功能。
摘要由CSDN通过智能技术生成

目录

前言

1. 串行通信介绍

1.1 同步通信

1.2 异步通信

2. 电路原理

2. 使用CubeMX进行源工程的配置

3. 代码编程

3.1 预备工作

3.2 uart.c和uart.h编写

3.3 终断文件的编写

3.4 main.c编写

3.4.1 系统时钟函数配置

3.4.2 头文件引用

3.4.3 变量声明

3.4.4 函数声明

3.4.5 函数定义

3.4.6 主要main函数部分

4. 测试

5. 总结


前言

因本人备赛蓝桥杯嵌入式省赛,故编写此学习笔记进行学习上的记录。

上文我们实现了LCD程序设计,本文我们进行异步的串口通信的程序设计。

1. 串行通信介绍

串行通信又叫做串行口通信,它又分为同步通信和异步通信两种方式

1.1 同步通信

同步通信时要建立发送方时钟对接收方时钟的直接控制,是双方达到完全同步。此时,传输数据的位之间的距离均为"位间隔"的整数倍,同时传送的字符间不留间隙,即保持位同步关系,也保持字符同步关系。发送方对接收方的同步可以是外同步也可以是自同步。通俗的来说,就是以一串字符为一个传送单位,字符间不加标识位,在一串字符开始用同步字符表示,硬件要求高,通信双方必须严格同步。

1.2 异步通信

异步通信是指通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程。为使双方的收发协调,要求发送和接收设备的时钟尽可能一致。以字符(构成的帧)为单位进行传输。发送方可以在任意时刻发送数据,所以用起始位和停止位标识每个字符的开始和结束,数据位从低到高传送。

  

2. 电路原理

通过查看查阅CT117E-M4产品手册的电路原理图可知,本开发板的PA9引脚为Tx,PA10引脚为Rx。

2. 使用CubeMX进行源工程的配置

我们在Pinout view的芯片引脚布局中将PA9设定为USART1_RX,PA10设定为USART1_Tx。

在Pinout&Configuration的Connectivity目录中选定USART1,将Mode选为Asynchronous,也就是异步模式,接下来在Parameter Setting设定需要的波特率、数字位等,我这里设定了波特率为9600,数字位为8为,无奇偶校验,一个停止位 。

将NVIC Interrupt Table中的中断使能打开,这是为了接收读取到的串口数据,当数据到来时,就进入我们编写的中断函数中。 

 在System Core目录的NVIC将USART1的中断优先级修改为1。

3. 代码编程

3.1 预备工作

接下来我们分别在Test工程里创建Test\Test_Project\Src\BSP\KEY\bsp_uart.c和Test\Test_Project\Inc\BSP\KEY\bsp_uart.h文件,这就是我们后面要编写的中间层代码文件。打开Test_Project工程,进行文件Group的添加。

在bsp_uart.c中添加依赖

#include "UART\bsp_uart.h"

 编译后可以看到在BSP文件夹下的效果。

在stm32g4xx_hal_conf.h中修改嘀嗒定时器的优先级为0

3.2 uart.c和uart.h编写

下面我们将Source工程生成的usart.c和usart.h的代码选择性的粘贴到我们构建的模块程序中,粘贴修改后的uart.c和uart.h 如下。

uart.h

#include "main.h"


extern UART_HandleTypeDef huart1;
void UART_Init(void);

uart.c

#include "UART\bsp_uart.h"

UART_HandleTypeDef huart1;


void UART_Init(void)
{
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART1)
  {
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
		
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
  }
}

void UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==USART1)
  {
    __HAL_RCC_USART1_CLK_DISABLE();


    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

    HAL_NVIC_DisableIRQ(USART1_IRQn);
  }
}

接下来我们进行代码编译,我们可以看到很多的报错,根据错误提示,应该是uart的相关依赖文件没有添加到工程,我们下来进行添加。

 进行文件Group的添加,添加stm32g4xx_hal_uart.c和stm32g4xx_hal_uart_ex.c。

 

进入stm32g4xx_hal_conf.h这个头文件,找到HAL_UART_MODULE_ENABLED宏定义,将注释取消掉。

再进行编译,发现没有error了!

3.3 终断文件的编写

 我们将Source工程中生成的stm32g4xx_it.c中的中断部分粘贴到Test_Project工程中的stm32g4xx_it.c

void SysTick_Handler(void)
{

  HAL_IncTick();

}

void USART1_IRQHandler(void)
{

  HAL_UART_IRQHandler(&huart1);

}

3.4 main.c编写

接下来我们编写main.c函数,主要去测试一下串口的收发,就设定一个简单的功能需求:

每个1s钟发送一次"Hello World\r\n",

接收到串口数据时将led灯点亮。

3.4.1 系统时钟函数配置

系统时钟函数SystemClock_Config添加uart部分的配置

RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
  Error_Handler();
}

3.4.2 头文件引用

#include "UART\bsp_uart.h"

3.4.3 变量声明

//变量声明
__IO uint32_t uwTick_Uart_Set_Point;//Uart减速

//Uart专用变量
char str[40];
uint8_t rx_buffer;

3.4.4 函数声明

//***子函数声明区
void Uart_Proc(void);

3.4.5 函数定义

其中,HAL_UART_Transmit函数的第一个参数为串口结构体指针,第二个参数为字符串地址,第三个参数为字符串长度,第四个参数为超时时间。

void Uart_Proc(void)
{
	if((uwTick - uwTick_Uart_Set_Point)<1000)return;//减速处理
	uwTick_Uart_Set_Point = uwTick;
	
	sprintf(str,"Hello World\r\n");
	HAL_UART_Transmit(&huart1,(unsigned char*)str,strlen(str),50);

}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	LED_Disp(0xFF);
	HAL_Delay(300);
	LED_Disp(0x00);
    HAL_UART_Receive_IT(&huart1, &rx_buffer, 1);
}

3.4.6 主要main函数部分

int main(void)
{
	HAL_Init();
	
    SystemClock_Config();
	LED_Init();

	UART1_Init();
	//*串口接收中断打开
	HAL_UART_Receive_IT(&huart1,&rx_buffer,1);
	
  while (1)
  {
		Led_Proc();
		Uart_Proc();
  }
}

4. 测试

打开串口助手,可以看到每隔1s中

接收到Hello World字符串。

使用串口助手发送任意字符,开发板的所有灯点亮后熄灭

5. 总结

综上,本次进行了异步串口通信的编程,通过CubeMx进行PA9、PA10引脚的配置,并通过Keil5进行相关代码的编写,在最后成功测试了串口的收、发的基本功能块。

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#串口介绍以及简单串口通信程序设计实现 源代码和串口程序介绍连接:https://www.cnblogs.com/JiYF/p/6618696.html 本站积分太贵,自己变得。。直接到连接地址下载代码 周末,没事干,写个简单的串口通信工具,也算是本周末曾来过,废话不多,直接到主题 串口介绍   串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。(至于再详细,自己百度) 串口应用:   工业领域使用较多,比如:数据采集,设备控制等等,好多都是用串口通信来实现!你要是细心的话,你会发现,目前家用国网智能电能表就具备RS485通信总线(串行总线的一种)与RS232可以相互转化(当然一般,非专业的谁也不会闲的蛋疼,趴电表上瞎看,最多也就看看走了多少度电) RS232 DB9介绍: 1.示意图 2.针脚介绍: 载波检测(DCD) 接受数据(RXD) 发出数据(TXD) 数据终端准备好(DTR) 信号地线(SG) 数据准备好(DSR) 请求发送(RTS) 清除发送(CTS) 振铃指示(RI) 3.实物图: 以下是我购买XX公司的一个usb转串口线:这个头就是一个公头,另一端是一个usb口 笨小孩串口工具运行图: 1.开启程序 2.发送一行字符串HelloBenXH,直接将针脚的发送和接收链接起来就可以测试了(针脚2 接受数据(RXD) 和3 发出数据(TXD))直接链接, C#代码实现:采用SerialPort 1.实例化一个SerialPort [csharp] view plain copy 在CODE上查看代码片派生到我的代码片 private SerialPort ComDevice = new SerialPort(); 2.初始化参数绑定接收数据事件 [csharp] view plain copy 在CODE上查看代码片派生到我的代码片 public void init() { btnSend.Enabled = false; cbbComList.Items.AddRange(SerialPort.GetPortNames()); if (cbbComList.Items.Count > 0) { cbbComList.SelectedIndex = 0; } cbbBaudRate.SelectedIndex = 5; cbbDataBits.SelectedIndex = 0; cbbParity.SelectedIndex = 0; cbbStopBits.SelectedIndex = 0; pictureBox1.BackgroundImage = Properties.Resources.red; ComDevice.DataReceived += new SerialDataReceivedEventHandler(Com_DataReceived);//绑定事件 }
利用stm32CubeMX,配合Keil,完成LED流水灯作业,即用GPIO端口完成3只LED红绿灯的周期闪烁。完成一个STM32的USART串口通讯程序.zip嵌入式优质项目,资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松copy复刻,拿到资料包后可轻松复现出一样的项目。 本人单片机开发经验充足,深耕嵌入式领域,有任何使用问题欢迎随时与我联系,我会及时为你解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明,项目具体内容可查看下方的资源详情。 【附带帮助】: 若还需要嵌入式物联网单片机相关领域开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步。 【本人专注嵌入式领域】: 有任何使用问题欢迎随时与我联系,我会及时解答,第一时间为你提供帮助,CSDN博客端可私信,为你解惑,欢迎交流。 【建议小白】: 在所有嵌入式开发中硬件部分若不会画PCB/电路,可选择根据引脚定义将其代替为面包板+杜邦线+外设模块的方式,只需轻松简单连线,下载源码烧录进去便可轻松复刻出一样的项目 【适合场景】: 相关项目设计中,皆可应用在项目开发、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面中 可借鉴此优质项目实现复刻,也可以基于此项目进行扩展来开发出更多功能

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值