STM32-(08):USART通信基础

上一篇:STM32-(07):串行通信基础(164芯片)下一篇:STM32-(09):USART库函数方式编程

USART通信

通用同步异步收发器<Universal Synchronous/Asynchronous Receiver/Transmitter>( USART )提供了一种灵活的方法来与使用工业标准 NRZ 异步串行数据格式的外部设备之间进行全双工数据交换。 USART 利用分数波特率发生器提供宽范围的波特率选择。

它支持同步单向通信和半双工单线通信。它也支持 LIN(局部互联网),智能卡协议和 irDA (红外数据组织 )SIRENDEC 规范,以及调制解调器( CTX / RTS )操作。它还允许许多处理器通信。

用于多缓冲器配置的 DMA 方式,可以实现高速数据通信。

• 全双工的异步通信
• 单线半双工通信
• 使用 DM A 的可配五的多緩冲通信
• 单独的犮送器和接收器使能位
• 检测标志
  接 收 缓 冲 器 满
  发 送 缓 冲 器 空
  传 输 结 束 标 志
• 校验控制
  发 送 校 验 位
  对 接 收 数 据 进 行 校 验
• 四个饼误检測标志
• 10个带标志的中断源

引脚介绍
任何USART通信,需要用到2个对外连接的引脚:RxD、TxD:
RxD是输入引脚,用于串行数据接收;
TxD是输出引脚,用于串行数据发送。

SCLK:发送器时钟输出。(同步模式用到)

在 lrDA 模式里需要下列引脚:
lrDA_RDI:lrDA模式下的数据输入。
lrDA_TDO:lrDA模式下的数据输出。

调制解调器模式中需要:
nCTS:清除发送
nRTS:发送请求

数据的接收过程示意图
数据串行输入到移位寄存器(一般8位),寄存器满了之后一次性全部送到输入数据缓冲器,缓冲器中设置一些标志量,一些控制信号,内核就可以通过中断的信号把数据读进来,如果内核用的是PMA,就回自动决定数据往哪个内存中放,实现数据的接收。
在这里插入图片描述

数据的发送过程示意图

在这里插入图片描述

异步串行通信协议

异步串行通信协议需要定义以下5个内容:
1.起始位
2.数据位(8、9)一般8位,9位是带奇偶校验
3.奇偶校验值(9位包含)
4.停止位(1、1.5、2个周期)
5.波特率设置(速度)

范例如图:
在这里插入图片描述

一般可以应用到如下一些场合:
1.芯片间的近距离通信
在这里插入图片描述
2.与PC机之间的通信(下图中的RS232只是电平的转换)
在这里插入图片描述
3.模块之间的远距离通信
RS-485通信电路示意图
在这里插入图片描述
RS-485接口的最大传输距离可以达3000米,最高传输速率10Mbps,且抗噪声干扰性好。
RS-485的电气特性:逻辑“1”以两线间的电压差为 +2V ~ +6V 表示:逻辑“0”以两线间的电压差为 -2 ~ -6V 表示。接口信号电平比 RS-232-C 降低了,该电平与TTL 电平兼容,柯方便与TTL电路连接。

数据发送过程

1.通过在USART_CR1寄存器上置位UE来激活USART
2.编程USART_CR1的M位来定义字长。
3.在USART_CR2中编程停止位的位数。
4.如果采用多缓冲器通信,配置USART_CR3中的DMA使能位(DMAT)。按多缓冲器通信中的描述配置DMA寄存器。
5.设置USART_CR1中的TE位,发送一个空闲帧作为第一次数据发送。
6.利用USART_BRR寄存器选择要求的波特率。
7.把要发送的数据写进USART_DR寄存器(此动作清除TXE位)。在只有一个缓冲器的情况下,对每个待发送的数据重复步骤7。

数据接收过程

1.将 USART_CR1寄存器的 UE 置1来激活 USART 。
2.编程 USART_CR1的 M 位定义字长
3.在 USART_CR2中编写停止位的个竣
4.如果需多缓冲器通信,选择 USART2_CR3中的 DMA 使能位( DMAT )。按多缓冲器通信所要求两配置 DMA 寄存器。
5.利用波特率寄存器 USART_ BRR 选择希望的波特率。
6.设置 USART_CR1的 RE 位。激活接收器,使它开始寻找起始位。

当一字符被接收到时:
RXNE 位被置位。它表明移位寄存器的内容被转移到 RDR 。
如果 RXNEIE 位被设置,产生中断。
在接收期间如果检测到帧错误,噪音或溢出错误,错 误标志将被置起.

涉及到的主要寄存器寄存器

1
2
2
1.状态寄存器
(Status register)
2.数据寄存器
3.波特率寄存器
4.控制寄存器1
5.控制寄存器2
6.控制寄存器3

代码

//main.c

//----------------头文件声明--------------------
#include"stm32f10x_lib.h"		//包含所有的头文件
#include<stdio.h>
//----------------函数声明--------------------
void Delay_MS(u16 dly);
void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART_Configuration(u32 BaudRate);

#define PA1 GPIOA->BSRR
#define PA0 GPIOA->BRR

#define GPIOA_ODR_A  (GPIOA_BASE+0x0C)
#define GPIOA_IDR_A  (GPIOA_BASE+0x08)
#define GPIOB_ODR_A  (GPIOB_BASE+0x0C)
#define GPIOB_IDR_A  (GPIOB_BASE+0x08)
#define GPIOC_ODR_A  (GPIOC_BASE+0x0C)
#define GPIOC_IDR_A  (GPIOC_BASE+0x08)
#define GPIOD_ODR_A  (GPIOD_BASE+0x0C)
#define GPIOD_IDR_A  (GPIOD_BASE+0x08)
#define GPIOE_ODR_A  (GPIOE_BASE+0x0C)
#define GPIOE_IDR_A  (GPIOE_BASE+0x08)

#define BitBand(Addr,BitNum)    *((volatile unsigned long *)((Addr&0xF0000000)+0x2000000+((Addr&0xfffff)<<5)+(BitNum<<2)))

#define PAout(n)   BitBand(GPIOA_ODR_A,n)
#define PAin(n)    BitBand(GPIOA_IDR_A,n)
#define PBout(n)   BitBand(GPIOB_ODR_A,n)
#define PBin(n)    BitBand(GPIOB_IDR_A,n)
#define PCout(n)   BitBand(GPIOC_ODR_A,n)
#define PCin(n)    BitBand(GPIOC_IDR_A,n)
#define PDout(n)   BitBand(GPIOD_ODR_A,n)
#define PDin(n)    BitBand(GPIOD_IDR_A,n)
#define PEout(n)   BitBand(GPIOE_ODR_A,n)
#define PEin(n)    BitBand(GPIOE_IDR_A,n)
/*******************************************************************************
* Function Name  : main
* Description    : Main program.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/ 
int  main(void)
{
	float Div;
	u16 M,F;
	u32 Bound,BRR;
	u8  data='A';
	//这里的两个函数都是利用库函数进行编程,下一篇文章会详细讲到
	RCC_Configuration();		//系统时钟设置
	GPIO_Configuration();	//GPIO设置,主要是TX,RX的引脚复用

	// 第一步:USART1模块的设置(参照手册一共有三个):
	//UE位使能、M位来定义字长、停止位的位数、TE位、BRR寄存器选择要求的波特率
	USART1->CR1 |= (1<<13);		//USART_CR1的第13位为UE位,置1使能
	USART1->CR1 &= ~(1<<12);	//USART_CR1的第13位为UE位,清0是 一个起始位,8个数据位,n个停止位
	USART1->CR2 &= ~(3<<12);	//USART_CR2的第12、13位为停止位,置00 是表示1个停止位
	USART1->CR1 |= (1<<3);	//USART_CR1的第3位为TE位,置1发送使能

	//关于波特率的设置,查看手册或者上方截图
	Bound = 9600;
	Div = (float)(72*1000*1000)/(Bound*16); //外设时钟为72Mhz
	M = Div;   //获取
	F = (Div-M)*16;
	BRR = M<<4|F;
	USART1->BRR = BRR;	

	//第二步:发送一个字符‘A’到USART1的DR
	for(F=0;F<30;F++)
	{
		USART1->DR = data;
		data++;
		//USART_SR状态寄存器的第6位表示发送完成,为1表示发送完成,这里判断是否为0,为0继续等待
		while((USART1->SR & (1<<6))==0) ; 
		
	}
	
}
/*******************************************************************************
* Function Name  : RCC_Configuration
* Description    : Configures the different system clocks.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RCC_Configuration(void)
{
	//----------使用外部RC晶振-----------
	RCC_DeInit();			//初始化为缺省值
	RCC_HSEConfig(RCC_HSE_ON);	//使能外部的高速时钟 
	while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);	//等待外部高速时钟使能就绪
	
	//FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);	//Enable Prefetch Buffer
	//FLASH_SetLatency(FLASH_Latency_2);		//Flash 2 wait state
	
	RCC_HCLKConfig(RCC_SYSCLK_Div1);		//HCLK = SYSCLK
	RCC_PCLK2Config(RCC_HCLK_Div1);			//PCLK2 =  HCLK
	RCC_PCLK1Config(RCC_HCLK_Div2);			//PCLK1 = HCLK/2
	RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);	//PLLCLK = 8MHZ * 9 =72MHZ
	RCC_PLLCmd(ENABLE);			//Enable PLLCLK

	while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);	//Wait till PLLCLK is ready
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);	//Select PLL as system clock
	while(RCC_GetSYSCLKSource()!=0x08);		//Wait till PLL is used as system clock source
	
	//---------打开相应外设时钟--------------------
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	//使能APB2外设的GPIOA的时钟	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);	//使能APB2外设的GPIOC的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	//GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);	 
		 
}


/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : 初始化GPIO外设
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/ 
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure USARTx_Tx as alternate function push-pull */		//第9脚复用为上拉
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure USARTx_Rx as input floating */	//第9脚复用为浮空输入
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

}

void USART_Configuration(u32 BaudRate)
{
	USART_InitTypeDef USART_InitStructure; 
	USART_InitStructure.USART_BaudRate = BaudRate; 
	USART_InitStructure.USART_WordLength = USART_WordLength_8b; 
	USART_InitStructure.USART_StopBits = USART_StopBits_1; 
	USART_InitStructure.USART_Parity = USART_Parity_No; 
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;  
	USART_Init(USART1, &USART_InitStructure);
	USART_Cmd(USART1, ENABLE);
}
上一篇:STM32-(07):串行通信基础(164芯片)下一篇:STM32-(09):USART库函数方式编程
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值