USART:(Universal Synchronous/Asynchronous Receiver/Transmitter)
通用同步/异步串行接收/发送器
USART是一个全双工通用同步/异步串行收发模块,该接口是一个高度灵活的串行通信设备。
串口设置的一般步骤可以总结为如下几个步骤:
1) 串口时钟使能,GPIO 时钟使能
2) 串口复位
3) GPIO 端口模式设置
4) 串口参数初始化
5) 开启中断并且初始化 NVIC(如果需要开启中断才需要这个步骤)NVIC :提供中断控制器,用于总体管理异常,称之为“嵌套向量中断控制器:Nested Vectored Interrupt Controller (NVIC)”。NVIC和处理器内核紧密相连.具体看这个点击打开链接
6) 使能串口
7) 编写中断处理函数
接下来我们按照以上步骤来编写串口初始化函数
#include "stm32f10x.h"
#include "usart.h"
#if EN_USART1_RX //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART_RX_STA=0; //接收状态标记
void uart_init(u32 bound)//这里有个疑问,为什么命名是uart,a代表异步,为什么是异步
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);//要用到的外设时钟使能,均在总线APB2上
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);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入模式
GPIO_Init(GPIOA,&GPIO_InitStructure);//由原理图得,这个端口接受串口数据
USART_InitStructure.USART_BaudRate=bound;//串口波特率
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits=USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity=USART_Parity_No;//parity奇偶性 无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//关闭硬件流控制(用于防止数据因接受不及丢失)
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能 中断请求通? ?
NVIC_Init(&NVIC_InitStructure);//根据指定的参数初始化NVIC寄存器
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART1, ENABLE); //使能串口1
}
这里没什么特别要说的,注意irq 是interrupt request,如果不打开,接收数据的中断请求信号就会发不出去,也就是说,单片机接收不到信息
再看中断函数
void USART1_IRQHandler(void)//串口1中断服务程序,中断服务程序的名字在core文件夹的汇编文件中定义
{
u8 Res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾),RXNE接收数据寄存器非空标志位
{
Res =USART_ReceiveData(USART1);//读取接收到的数据
if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
else USART_RX_STA|=0x8000;//接收完成了
}
else //还没收到0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
}
#endif
这里我一开始看不懂,发现前面原来有讲,是我没看。。。。
主函数如下
#include "stm32f10x.h"
#include "usart.h"
void delayms(u16 a)
{
u16 i,j;
for(i=0;i<a;i++)
{
j=8000;
while(j--);
}
}
int main(void)
{
u8 t;
u8 len;
u16 times=0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
uart_init(9600);//串口初始化为9600
while(1)
{
if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
for(t=0;t<len;t++)
{
USART1->DR=USART_RX_BUF[t];
while((USART1->SR&0X40)==0);//等待发送结束
}
USART_RX_STA=0;
delayms(10);
}
}
}
今后继续补充