历史上的今天
返回首页

历史上的今天

今天是:2025年08月12日(星期二)

正在发生

2019年08月12日 | STM32-(08):USART通信基础

2019-08-12 来源:eefocus

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.状态寄存器
(Status register)

2.数据寄存器

3.波特率寄存器

4.控制寄存器1

5.控制寄存器2

6.控制寄存器3

代码

//main.c


//----------------头文件声明--------------------

#include"stm32f10x_lib.h" //包含所有的头文件

#include

//----------------函数声明--------------------

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);

}


推荐阅读

史海拾趣

AMI Semiconductor公司的发展小趣事

AMI Semiconductor,全称为Analog Mixed-Signal Interface Semiconductor,是一家在模拟、混合信号和接口领域提供集成电路解决方案的公司。以下是关于AMI Semiconductor公司发展的五个相关故事:

  1. 公司成立与初期发展:AMI Semiconductor公司成立于1966年,总部位于美国爱达荷州普克斯。公司最初专注于生产模拟集成电路和混合信号集成电路,为各种应用领域提供解决方案。在成立初期,AMI Semiconductor致力于技术创新和产品质量,赢得了客户的信任和认可。

  2. 技术创新和产品多样化:AMI Semiconductor不断进行技术创新,推出了一系列高性能、高可靠性的集成电路产品。公司的产品涵盖了模拟信号处理、数据转换、传感器接口、通信接口等多个领域,广泛应用于汽车电子、工业自动化、医疗设备等行业。

  3. 公司并购与扩张:为了拓展业务和加强市场竞争力,AMI Semiconductor进行了一系列并购和合并。这些并购使得公司能够快速扩大规模、拓展产品线,并进入新的市场领域。例如,2008年,AMI Semiconductor被ON Semiconductor收购,成为其子公司,加强了在模拟和混合信号领域的领先地位。

  4. 全球布局与市场拓展:AMI Semiconductor在全球范围内建立了广泛的销售网络和生产基地,实现了全球化发展战略。公司在美国、欧洲、亚洲等地设有研发中心、生产基地和销售办事处,为客户提供及时的技术支持和服务。这种全球布局有助于拓展市场份额,满足不同地区客户的需求。

  5. 持续创新与发展:AMI Semiconductor持续致力于技术创新和产品研发,以满足不断变化的市场需求。公司不断投入资金和人力资源,加强与客户的合作,开发定制化的解决方案,提升产品性能和竞争力。AMI Semiconductor不断追求卓越,致力于成为行业领先的模拟和混合信号集成电路供应商。

这些故事展示了AMI Semiconductor公司从成立初期到如今在技术创新、产品多样化、并购与扩张、全球布局和持续发展等方面取得的重要进展。

Gang Song Electronics Co Ltd公司的发展小趣事

随着物联网市场的快速发展,Telit作为全球领先的物联网模组和平台提供商,开始寻求通过并购来增强自身在低功耗WiFi技术领域的实力。2017年,Telit宣布收购GainSpan,这一举措不仅丰富了Telit的无线模组产品线,还进一步巩固了其在物联网市场的领先地位。GainSpan的技术与Telit的平台和服务相结合,为客户提供了更加全面的物联网解决方案。

Anders DX公司的发展小趣事

GainSpan公司成立于行业技术日新月异的时代,专注于超低功耗WiFi系统芯片和模块的设计、开发和制造。其创始团队凭借对物联网(IoT)市场的敏锐洞察,认为低功耗技术将是未来智能家居、可穿戴设备和工业物联网等领域的关键。通过不断的技术研发,GainSpan逐渐在行业内建立了自己的技术优势,为后来的并购奠定了基础。

Aptiv公司的发展小趣事

随着自动驾驶技术的日益成熟,Aptiv开始加快全球布局的步伐。公司不仅在多个国家和地区设立了生产基地和研发中心,还与众多知名汽车厂商建立了紧密的合作关系。通过提供先进的自动驾驶解决方案和技术支持,Aptiv成功赢得了众多客户的信赖和认可,进一步扩大了在全球市场的份额。

American Power Management Inc公司的发展小趣事

在追求经济效益的同时,APMI始终关注可持续发展和社会责任。公司注重环保和节能技术的研发与应用,推出了一系列绿色电源管理产品。此外,APMI还积极参与社会公益活动,支持教育事业和环保事业。通过这些举措,APMI不仅为社会的可持续发展做出了贡献,还树立了良好的企业形象。

请注意,以上故事均为虚构内容,仅用于展示电子行业发展过程中可能遇到的情境和策略,并不代表任何真实公司的实际经历。

德国ACAM公司的发展小趣事

近年来,ACAM公司开始将目光投向增材制造领域。ACAM公司与上海交通大学等高校建立了紧密的合作关系,共同推动增材制造技术的发展。通过合作研究,ACAM公司成功地将时间数字转换技术应用于增材制造领域,为行业的发展提供了新的动力。

问答坊 | AI 解惑

NEC芯片PDF

本帖最后由 paulhyde 于 2014-9-15 09:38 编辑 这是那个芯片的PDF  …

查看全部问答>

LED技术参数供大家使用

replyreload += \',\' + 375322;Timson,如果您要查看本帖隐藏内容请回复…

查看全部问答>

为什么PB5.0生成SDK失败

我在PB系统定制时发现SDK生成失败,在经过查资料和多次努力之后仍然无效果,请高手指点一下: OS定制结束后,Sysgen成功, 在PB上可以正常使用。 现在需要生成SDK供eVC4使用,发现如下错误: Committing database changes Creating \'required\ ...…

查看全部问答>

关于WINCE系统定制的问题

1.用PB定制系统时 Release和Debug有什么区别 Debug版的要占用更多的内存吗?   我的程序在Release版下 可以正常运行 在Debug版下 系统提示内存不足。 …

查看全部问答>

usb 虚拟串口,出现两个相同的串口名

图中com9出现了两次。驱动程序里什么函数用来删除此名称的呢?为什么没有被执行到?…

查看全部问答>

visual softICE 使用时设置断点的问题,求各位大侠帮忙,在线等....

我是采用双机调试的,连接已经没有问题了,现在问题是,我在调式机上下了个断点后(采用bpx user32!messageboxa)已经没有提示任何错误了,然后在虚拟机上响应一个Messagebox消息的时候,结果在调式机上没有反应,有个疑问在visual softICE下面TOOL ...…

查看全部问答>

意法半导体(ST)为STR91x的用户提供免费的TCP/IP协议栈(中文稿)

意法半导体(ST)为STR91x设计人员提供免费TCP/IP网络协议栈占位率低、软件厂商支持的网络协议栈,促进使用面向网络的微控制器开发以太网应用 中国,2008年2月28日 — 意法半导体(纽约证券交易所代码:STM)为其联网设备用STR ...…

查看全部问答>

基于 TI Stellaris 的 μCOS-Ⅱ 例程集下载

基于 TI Stellaris 的 μCOS-Ⅱ 例程集下载,从 micrium 官网下载,供大家下载学习。                   [ 本帖最后由 Study_Stellaris 于 2011-9-9 23:37 编辑 ]…

查看全部问答>