stm32-串口

 

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)//
这里有个疑问,为什么命名是uarta代表异步,为什么是异步
{
    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);                    //使能串口
}

这里没什么特别要说的,注意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

这里我一开始看不懂,发现前面原来有讲,是我没看。。。。

https://img-blog.csdn.net/20170215232033064?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luYXRfMzA0NTcwMTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

 

主函数如下

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

http://images2015.cnblogs.com/blog/1104670/201707/1104670-20170702144726071-2136566276.jpg

 

猜你喜欢

转载自blog.csdn.net/sinat_30457013/article/details/89383396