上一篇:STM32-(07):串行通信基础(164芯片) | 下一篇:STM32-(09):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 位被设置,产生中断。
在接收期间如果检测到帧错误,噪音或溢出错误,错 误标志将被置起.
涉及到的主要寄存器寄存器
|
|
|
|
---|---|---|---|
(Status register) |
|||
|
|||
|
|||
|
|||
|
|||
|
//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);
}
上一篇:STM32-(07):串行通信基础(164芯片) | 下一篇:STM32-(09):USART库函数方式编程 |
---|