STM32F407 芯片的学习 day06 UART串口通信 的知识与代码

1.UART串口通信

处理器与外部设备通信的两种方式

并行通信    -传输原理:数据各个位同时传输。  

优点:速度快    

缺点:占用引脚资源多

串行通信    -传输原理:数据按位顺序传输。

 优点:占用引脚资源少    

缺点:速度相对较慢


2.按照数据传送方向分为:

1.单工:数据传输只支持数据在一个方向上传输

2.半双工:允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;

3.全双工:允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。


 3.串行通信的通信方式

同步通信:带时钟同步信号传输。 -SPI,IIC通信接口(I2C)

异步通信:不带时钟同步信号。 -UART(通用异步收发器),单总线

 


4.UART异步通信方式引脚连接方法:   

 -RXD:数据输入引脚。数据接受。   

 -TXD:数据发送引脚。数据发送。

STM32串口异步通信需要定义:

1. 起始位

2. 数据位(8位或者9位)

3.奇偶校验位(第9位)

4. 停止位(1,1.5,2位)  

5.波特率设置

串口按位(bit)发送和接收字节的通信方式。
通信可以分为同步串口通信和异步串口通信。
波特率:是一个衡量符号传输速率的参数。在单片机使用中,常用的波特率有9600、115200等。
数据位:通信中实际数据位的参数。
停止位:单个包的最后位。典型的值为1,1.5和2位。
校验位:判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。


 



 5.USART数据的发送/接收原理     

 

串行发送:CPU内部还是并行数据(即:保存在发送数据寄存器),按照发送时钟逐字位的将发送数据存入到移位寄存器,然后再通过TxD发送引脚逐位发送出去。

 

串口接收:外部数据逐位从RxD引脚被接收,按照接收时钟,又逐字位的将接收到的数据存入到移位寄存器,然后再保存到接收数据寄存器中,并被CPU读取。

 

 

注意:串口如果使用printf函数,一定要记得重写fputc函数,以及勾选Use Micro LIB。如果不勾选微库,则要添加“半主机模式的相应代码”,可百度查找。

重写的代码:

int fputc (int ch,FILE *f)
{
    while ( (USART1->SR & 0x40) == 0 );//判断上一次发送是否完成。
    USART1->DR=(u8) ch;
    return ch;
}


6.i2c协议-物理层 (通信方式 与今天的内容无关 !!)

 I2C主要特点如下所示:

只需要两条总线;

没有严格的波特率要求,例如使用RS232,主设备生成总线时钟;

所有组件之间都存在简单的主/从关系,连接到总线的每个设备均可通过唯一地址进行软件寻址; I2C是真正的多主设备总线,可提供仲裁和冲突检测;

传输速度分为四种模式:

1、标准模式:Standard Mode=100 Kbps(传输速度慢了,用的少)

2、快速模式:Fast Mode=400 Kbps(使用最多)

3、高速模式:High speed mode=3.4 Mbps(大部分设备不支持这么高的频率)

4、超快速模式:Ultra fast mode=5 Mbps 最大主设备数:无限制; 最大从机数:理论上是127(7位数存储,2的7次方等于128)。 另外连接到相同总线的I2C数量受到总线的最大电容400pF限制(测试SCL总线的电容值)。实际上还没到128V,就到达到电容限制了。一般都不会使用这么多设备,设备多了,通讯速度跟不上。

 i2c通信协议通信协议:用来实现数据传输。   

 i2c物理总线:SCL(时钟线)    SDA(数据线)  

   i2c通信协议是 串行、同步、半双工 的通信方式。   

 i2c物理总线中,SCL时钟线只能由MCU来控制。SDA数据线可以收发数据。i2c通信必须是MCU和i2c从设备之间的双方通信。一条i2c总线上可以挂载多个i2c从设备。在进行通信时,必须是MCU和i2c从设备之间的通信,MCU一次只能和一个i2c从设备通信。一条i2c总线上如果挂载多个i2c从设备,i2c总线通过器件地址来区别不同的i2c从设备。器件地址:每一个i2c从设备挂载到i2c总线之后,必须得到的一个在该总线上的编号。器件地址一般是一个8位的数据。器件地址的组成:4(设备ID)   +   3(可编程地址)   +  1(读写控制位) 总结:i2c通信协议是同步通信,MCU通过器件地址查找要通信的i2c从设备。

    i2c通信协议时序:空闲信号、 起始信号、 读数据、 写数据、 发送应答、 接收应答、 终止信号

空闲信号:SCL : 高    SDA : 高

起始信号:SCL :高     SDA :由高变低

读数据:   SCL :高      SDA :获取SDA上的电平

写数据:   SCL :低      SDA :改变SDA电平状态

终止信号:SCL :高      SDA :由低变高


 7.初始化串口 :

 

状态寄存器

 

当要发送数据时,TDR寄存器将存放着的待发送的数据传输到移位寄存器,当TDR的数据全部移位到移位寄存器,TXEIE置1,表明数据传输到移位寄存器。

当传送数据完成时,TC位置1。

当要接收数据时,移位寄存器把数据传输到DR寄存器中,当传输完成后,RXNE位置1,表明数据已完全传输到DR寄存器中,已准备好随时被读取。


 

 

 数据寄存器

串口通信中,STM32F4有一个专门的数据寄存器用于存放数据,该寄存器的[8:0]位(共9位)为有效数据位,用于存放数据值。

( 数据寄存器包含两个寄存器,一个用于发送 (TDR),一个用于接收 (RDR) )

而我们知道一个字节是一个8位长的数据单位,可用一个字节表示一个字符、数字或其他字符,或者系列二进制位。

串口通信中寄存器每一次通过USART_SendData或USART_ReceiveData函数可以发送或接收一个字节的数据。

波特率寄存器


 8.代码:

以 STM32F407 的串口1为例,跟大家讲下如何配置一个串口,使其能进行数据收发。
(1)串口初始化
在这一步中,需要:
① 对该串口使用到的 IO 口进行初始化和使能相应的时钟树,并对端口进行复用映射;
② 中断配置 (主要是一个优先级);
③ 串口初始化配置(奇偶校验、收发配置等);
④ 串口使能;

usart.c

void usart1_init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;//定义对象
	USART_InitTypeDef USART_InitStruct;//定义对象
	NVIC_InitTypeDef NVIC_InitStruct;//定义对象

	//1.时钟使能
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟	
	
	//2.引脚初始化
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//设置引脚为复用模式
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;//推挽输出
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;//引脚的配置
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //上拉电阻
	GPIO_InitStruct.GPIO_Speed = GPIO_Fast_Speed;//引脚速度
	GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化
	
    //串口1对应引脚复用映射
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
	
	//3.串口初始化
	USART_InitStruct.USART_BaudRate = 115200;//串口波特率
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
	USART_InitStruct.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStruct.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_Init(USART1,&USART_InitStruct);//初始化串口1

	//4.中断优先级配置    nvic  Ustart1
	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;   //子优先级
	NVIC_Init(&NVIC_InitStruct);	//根据指定的参数初始化VIC寄存器
	
	//5.开启中断
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	//6.中断使能
	USART_Cmd(USART1,ENABLE);
}
	

int fputc (int ch,FILE *f)//使用printf() 需要定义
{
    while ( (USART1->SR & 0x40) == 0 );//判断上一次发送是否完成。
    USART1->DR=(u8) ch;
    return ch;
}
	
void USART1_IRQHandler(void)//中断函数
{
	char temp;
	if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{
		temp = USART_ReceiveData(USART1);//(USART3->DR);	//读取接收到的数据
		switch(temp)
		{
			case '1':allshine();break;
			case '2':allclose();break;
			case '3':openbeep();break;
			case '4':closebeep();break;
		}
	}
	USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}

 main.c 

#include "stm32f4xx .h"
#include "usart.h"
#include "stdio .h "





int main ()
{

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    usartl_init();
    printf( "hello ! ");
    return 0;

}

 


9.补充的知识

 

 或者用这个:

 

 

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个基于STM32F407芯片串口通信代码示例,使用的是HAL库。 ```c #include "stm32f4xx_hal.h" UART_HandleTypeDef huart2; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART2_UART_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART2_UART_Init(); uint8_t txData[] = "Hello, world!\r\n"; while (1) { HAL_UART_Transmit(&huart2, txData, sizeof(txData), HAL_MAX_DELAY); HAL_Delay(1000); } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 336; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 7; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = 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_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } static void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_USART2_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } ``` 这段代码设置了USART2串口为115200波特率,8位数据位,1位停止位,无校验位,进行了初始化和GPIO配置。在`main`函数中,我们不断发送“Hello, world!”字符串,并使用`HAL_Delay`函数延迟1秒钟。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值