基于cubemx+keil 的STM32F405RGT6 串口通信发送与接收

 一、串口的介绍

    1.什么是串口通信

串口通信是一种简单的通信协议,通信协议就是双方在通信过程中需要共同遵守的约定,数据的发送方按照某种协议把数据调制成某种可以传输的信号,接收方就可以使用相同的协议从信号中解析出数据,比如说人的语言就可以看作是一种通信协议,说话的人会把想要说的话调制在声波中进行传输,收听的一方就会从声波上解析出这一句话,这个过程就使用了“语言”这个协议,只有当双方都掌握这种语言的时候,交谈才能成功,不然就是鸡对鸭讲。

串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信
单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大地扩展了单片机的应用范围,增强了单片机系统的硬件实力

2、串口传输一个字节过程

串口一般由三根线组成,因为我们是通过高低电平来传输信号的,而两根线才能够形成电势差,我们定义高电平表示逻辑1,低电平表示逻辑0,还有一根线接单片机的GND相连

注意单片机与电脑TX RX要交替连接     注意单片机与电脑的TX RX线要交替连接,一般使用USB转TTL模块来将单片机与电脑连接

(1)、首先在空闲状态下,也就是没有数据传输的时候,传输线上的电平是高电平,表示逻辑1,当发送端需要发送数据的时候,就会将电平拉低,作为起始信号,这是,接收端检测到了电平的高低变化,就会做好接收准备,起始信号会占用一个位的时间,称为起始位

(2)、之后,进入数据传输阶段,发送端会将字节每一位依次发出,发送方式就是让每一位对应的电平持续一段时间,接收端就会不断的对传输线上的电平信号进行采样,判断发哦四年方发出的是0还是1

(3)、当完成了数据的传输之后,进入检验阶段,接下来这一个位叫做校验位,可以对传输的正确与否进行校验,检验位分为奇校验和偶检验,若配置位奇检验,那么发送出来的数据位和检验位里面,逻辑1的个数是奇数,偶检验则为偶数,如果接收端发现不是奇数(偶数)的话,说明数据传输过程中发生了错误。

(4)、最后是停止位,发送方将电平拉高,表示传输完成,可配置成1位或2位,停止位长的话可以让传输更加稳定,但传输数据的速度也就慢了一点。

以上就是串口通信时序介绍,下面是时序图

此外还需配置一个很重要的参数,波特率,单位是bit/s,表示每秒可以传输多少个这样的位,典型的波特率配置是9600以及他的整数倍频和分频,很明显,波特率高的话传输速率就会变快,但同时出现误码的错误也会变高,鱼和熊掌不可兼得。

需要注意的是,发送端和接收端必须配置成一样的,否则是没有办法进行通信的

3、一些传输例子

由上两图可知,串口是低位先行,先发送低位,在发送高位,从最低位开始依次发出

二、cubemx配置

串口也是STM32的外设,我们并不需要去手动操控IO的高低电平,而是在配置好协议参数后,在程序中调用函数

1、配置基本工程

(1)先进行工程的基础配置

首先用cubemx新建一个工程,点击下方ACCESS TO MCU SELECTOR

然后按下面顺序操作,添加自己芯片型号,然后进行第三步Start Project 生成工程

然后进行每次创建工程都需要做的三板斧

第一板斧:如下操作,否则不能烧录

第二板斧:选择高速时钟为晶振

第三板斧:系统时钟SCLK配置为最大,有显示你的板子是多大的,照写就行,然后按回车键

为了生成keil文件,还需进行以下两步配置

最后点击生成代码(先写基本工程配置,下面进行串口配置)

点击第一个蓝色的打开文件,点击第二个打开工程(keil文件)

2、串口配置

3、串口发送

接线:

单片机                电脑

RX------------------ TX

TX ------------------ RX

GND---------------- GND

(1)阻塞式串口收发(当我们要传输的数据都传输完了,这个函数才会执行结束)

while (1)
  {
  
	HAL_UART_Transmit(&huart2,(uint8_t*)"ojbk  ",5,0xff);
	HAL_Delay(500);
  
  }

}

这段代码,简单来说,就是 哪个串口发送,发送什么,长度多少,0xff表示延时时间,单位是毫秒,如果超出这个时间还没发送完毕就结束发送,剩余的不发了

使用printf函数来进行串口输出:

首先添加头文件#include "stdio.h"

然后重写fputc函数,因为printf内部就是调用这个函数来进行单个字符输出的

int fputc(int c,FILE *stream)
{
  uint8_t ch[1]={c};
  HAL_UART_Transmit(&huart2,ch,1,0xff);
  return c;
}

结果展示,这里没有结果的话 把魔术棒里面target---use microlib钩选上

(2)阻塞式接收

 while (1)
  {
  
   
		uint8_t buf[5];//缓存数组
		HAL_UART_Receive(&huart2,buf,5,0xffff);//电脑发送数据给单片机,用buf储存
		HAL_UART_Transmit(&huart2,buf,5,0xffff);//单片机像电脑发送数据验证接收正确与否
/*
上面两个函数的数据长度,超时时间都给多点,不然会有奇奇怪怪的事情发生,别问我是怎么知道的
*/
		HAL_Delay(500);
   
  }

使用scanf函数来进行串口接收:

重写fgect函数

/*
scanf内部就是通过这个函数来进行单个字节的读入的
我们需要在这个函数中通过串口读入一个字节
然后把他作为返回值返回回去
*/

int fgetc(FILE *stream)
{
   uint8_t ch[1];
   HAL_UART_Receive(&huart2,ch,1,0xff);
   return ch[0];

}
 while (1)
  {
		int val=0;
		scanf("%d",&val);
		printf("%d\r\n",val);
		HAL_Delay(500);
}

(2)使用中断进行串口收发

由于使用阻塞的方式收发太浪费CPU资源,而且会影响整个程序的运行,数据实际上都是由硬件自动进行传输的,软件只需要指定好发送的数据就行,所以使用阻塞式时,大部分的时间都被浪费在了等待硬件完成传输的过程中,为解决这个问题,故使用中断方式进行收发

步骤:

首先在cubemx里面把串口的中断给打开,在NVIC中使能USART2中断,并调一下优先级,然后点击生成代码

串口发送

/*
跟上面的阻塞式差不多一样,只是少了个超时时间
每发完一个字节进入一个中断,然后在中断中HAL库会再触发下一个字节的发送,直到发完全部数据
所以说此函数不需等待数据发送完毕才会退出
*/,他只是触发了中断发送的流程

while (1)
  {
		HAL_UART_Transmit_IT(&huart2,(uint8_t *)"ojbk",5);
		HAL_Delay(500);
  
  }

回调函数,在完成了所有数据的发送之后,会进入回调函数

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{

}

串口接收:

uint8_t buffer[5];//接收数组,这是全局变量
//HAL_UART_Receive_IT(&huart2,buffer,3);//接收函数,每接收到一个字节进入一次中断,并保存到接收区里面,所以buffer不能为局部变量,不然有可能接收到数据存入时局部变量已经被销毁了,没有办法进行保存
//当接收完指定数量的字节后,就会调用以下回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
   HAL_UART_Transmit_IT(&huart2,buffer,3);//把接收到的数据发送回去
   HAL_UART_Receive_IT(&huart2,buffer,3);//再开启下一次接收
}

 HAL_UART_Receive_IT(&huart2,buffer,3);//开启接收

while()
{
}

这个代码有bug,还未解决,只有第一次发送的是正确的,后续发送结果如下所示求大佬指正

以上bug解决方法,把串口发送长度加2,因为串口接收有两个字节长度不可见

uint8_t buffer[5];//接收数组,这是全局变量
//HAL_UART_Receive_IT(&huart2,buffer,3);//接收函数,每接收到一个字节进入一次中断,并保存到接收区里面,所以buffer不能为局部变量,不然有可能接收到数据存入时局部变量已经被销毁了,没有办法进行保存
//当接收完指定数量的字节后,就会调用以下回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
   HAL_UART_Transmit_IT(&huart2,buffer,3);//把接收到的数据发送回去
   HAL_UART_Receive_IT(&huart2,buffer,5);//再开启下一次接收
}

 HAL_UART_Receive_IT(&huart2,buffer,5);//开启接收

while()
{
}

总结:使用中断方式收发的流程

1.调用函数开启一次中断收发的流程

2.每发送或接收到一个字节会进入中断由HAL进行处理,用户程序无需参与

3.传输完指定数量的字节后,HAL调用发送或接收完成回调函数

(3)、用DMA进行串口收发

cpu只需要为DMA分配好内存空间就行,不用每个字节都进中断进行处理

DMA配置

点击Add分别添加发送和接收的DMA,然后点击生成代码

用DMA进行串口发送函数

 HAL_UART_Transmit_DMA(&huart2,buffer,3);

用DMA进行串口接收函数

 HAL_UART_Receive_DMA(&huart2,buffer,5);

这两个函数跟阻塞式的用法一样

//发送
  while (1)
  {
	HAL_UART_Transmit_DMA(&huart2,(uint8_t *)"ojbk\n",5);
    HAL_Delay(500);
  }

//接收
   while (1)
  {
	uint8_t buffer[5];
	HAL_UART_Receive_DMA(&huart2,buffer,5);//½ÓÊÕ
	HAL_UART_Transmit_DMA(&huart2,buffer,5);
	HAL_Delay(500);
	
  }

  • 30
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STM32F405RG是一款基于ARM Cortex-M4内核的微控制器,它属于STM32系列的F400产品线。这款MCU特别适合对性能、功耗和功能需求较高的应用,如工业控制、物联网设备、消费电子等。 该型号的主要特点包括: 1. **高性能**:Cortex-M4处理器提供高达168MHz的CPU频率,具有浮点运算能力和硬件乘法器,支持高效的实时任务处理。 2. **丰富的外设**:内置多种通信接口,如USART、SPI、I2C、CAN、USB以及高级定时器和ADC/DAC,方便数据传输和信号处理。 3. **大内存**:具有Flash存储器(通常有512KB至2MB之间),以及RAM(最大可达192KB),支持程序的高效运行。 4. **低功耗模式**:支持多种省电模式,有助于延长电池寿命。 5. **丰富开发资源**:ST提供了CubeMX图形化配置工具和详细的文档,便于快速入门和软件开发。 如果你打算学习STM32F405RGT6,可以按照以下步骤进行: 1. **理解基本原理**:首先熟悉嵌入式系统和微控制器的工作原理。 2. **下载资料**:获取官方的STM32Cube库和开发环境(如Keil MDK或SW4STM32)。 3. **配置开发板**:设置开发环境,连接并配置你的STM32F405RG开发板。 4. **编写基础程序**:从LED闪烁、GPIO操作开始,逐渐掌握中断、定时器和串口通信等核心功能。 5. **深入学习**:阅读参考手册,了解特有功能,如ADC采样、PWM输出等,并尝试实际项目。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值