zoukankan      html  css  js  c++  java
  • stm32串口

    STM32的串口是相当丰富的,功能也非常强劲。最多可提供5路串口(MiniSTM32使用的是STM32F103RBT6,具有3个串口),有分数波特率发生器、支持单线光通信和半双工单线通讯、支持LIN、智能卡协议和IrDASIR ENDEC规范(仅串口3支持)、具有DMA等。
    串口最主要的设置。就是波特率的设置。STM32的串口使用起来还是蛮简单的,仅仅要你开启了串口时钟,并设置对应IO口的模式,然后配置一下波特率,数据位长度。奇偶校验位等信息。就能够使用了。以下,我们就简介下这几个与串口基本配置直接相关的寄存器。
    1,串口时钟使能。串口作为STM32的一个外设,其时钟由外设时钟使能寄存器控制。这里我们使用的串口1是在APB2ENR寄存器的第14位。

    APB2ENR寄存器在之前已经介绍过了,这里不再介绍。仅仅是说明一点。就是除了串口1的时钟使能在APB2ENR寄存器,其它串口的时钟使能位都在APB1ENR。


    2,串口复位。当外设出现异常的时候能够通过复位寄存器里面的相应位设置,实现该外设的复位,然后又一次配置这个外设达到让其又一次工作的目的。一般在系统刚開始配置外设的时候,都会先运行复位该外设的操作。串口1的复位是通过配置APB2RSTR寄存器的第14位来实现的。

    APB2RSTR寄存器的各位描写叙述例如以下:


    [转载]stm32串口

    图3.3.1.1寄存器APB2RSTR各位描写叙述


    从上图可知串口1的复位设置位在APB2RSTR的第14位。通过向该位写1复位串口1。写0结束复位。其它串口的复位位在APB1RSTR里面。
    3,串口波特率设置。

    每一个串口都有一个自己独立的波特率寄存器USART_BRR,通过设置该寄存器达到配置不同波特率的目的。该寄存器的各位描写叙述例如以下:
    [转载]stm32串口

    图3.3.1.2寄存器USART_BRR各位描写叙述


    前面提到STM32的分数波特率概念,事实上就是在这个寄存器里面体现的。最低4位用来存放小数部分DIV_Fraction,[15:4]这12位用来存放整数部分DIV_Mantissa。高16位未使用。这里波特率的计算通过例如以下公式计算:[转载]stm32串口

    这里的fpclkx(x=1、2)是给外设的时钟(PCLK1用于串口2、3、4、5,PCLK2用于串口1),USARTDIV是一个无符号的定点数,它的值能够有串口的BRR寄存器值得到。而我们更关心的是怎样从USARTDIV的值得到USART_BRR的值,由于一般我们知道的是波特率,和PCLKx的时钟,要求的就是USART_BRR的值。


    以下我们来介绍怎样通过USARTDIV得到串口USART_BRR寄存器的值,如果我们的串口1要设置为9600的波特率,而PCLK2的时钟为72M。这样,我们依据上面的公式有:USARTDIV=72000000/9600*16=468.75
    那么得到:DIV_Fraction=16*0.75=12=0X0C; DIV_Mantissa= 468=0X1D4;
    这样,我们就得到了USART1->BRR的值为0X1D4C。仅仅要设置串口1的BRR寄存器值为0X1D4C就能够得到9600的波特率。
    4。串口控制。STM32的每一个串口都有3个控制寄存器USART_CR1~3,串口的非常多配置都是通过这3个寄存器来设置的。这里我们仅仅要用到USART_CR1就能够实现我们的功能了。
    [转载]stm32串口

    BIT 13: 串口功能;
    BIT 12: MODE。字长。

    0: 1个開始位,8个数据位,1位停止位(默认);1: 1个開始位。9位数据位。1位停止位(默认)。
    *注意:停止位的长度可在USART_CR2寄存器中设置。
    BIT 11: WAKE 唤醒功能
    BIT 10: 校检使能位,当激活奇偶校验功能时。置位该位将自己主动往要数据传输的高位字节处插入就校验位。
    BIT 09: Parity Selection,0:偶校验;1:奇校验。


    BIT 08: PE Interrupt Enable
    BIT 07: 发送缓冲区空中断使能位

    BIT 06: 发送完毕中断使能位

    BIT 05: 接收缓冲区非空中断使能位

    BIT 04: Idle Interrupt Enable
    BIT 03: Transfer Enable
    BIT 02: Receive Enable
    BIT 01: Receiver Wakeup
    BIT 00: Send Break


    5,数据发送与接收。STM32的发送与接收是通过数据寄存器USART_DR来实现的。这是一个双寄存器,包括了TDR和RDR。当向该寄存器写数据的时候。串口就会自己主动发送,当收到收据的时候,也是存在该寄存器内。

    该寄存器的各位描写叙述例如以下:
    [转载]stm32串口

    图3.3.1.3寄存器USART_DR各位描写叙述


    能够看出。尽管是一个32位寄存器。可是仅仅用了低9位(DR[8:0])。其它都是保留。
    DR[8:0]为串口数据。包括了发送或接收的数据。因为它是由两个寄存器组成的,一个给发送用(TDR)。一个给接收用(RDR),该寄存器兼具读和写的功能。TDR寄存器提供了内部总线和输出移位寄存器之间的并行接口。RDR寄存器提供了输入移位寄存器和内部总线之间的并行接口。


    当使能校验位(USART_CR1种PCE位被置位)进行发送时。写到MSB的值(依据数据的长度不同,MSB是第7位或者第8位)会被后来的校验位该代替。
    当使能校验位进行接收时,读到的MSB位是接收到的校验位。


    6。串口状态。串口的状态能够通过状态寄存器USART_SR读取。

    USART_SR的各位描写叙述例如以下:
    [转载]stm32串口

    图3.3.1.4寄存器USART_SR各位描写叙述


    这里我们关注一下两个位,第5、6位RXNE和TC。
    RXNE(读数据寄存器非空),当该位被置1的时候,就是提示已经有数据被接收到了,而且能够读出来了。这时候我们要做的就是尽快去读取USART_DR。通过读USART_DR能够将该位清零。也能够向该位写0。直接清除。
    TC(发送完毕),当该位被职位的时候。表示USART_DR内的数据已经被发送完毕了。

    假设设置了这个位的中断,则会产生中断。该位也有两种清零方式:1)读USART_SR,写USART_DR。

    2)直接向该位写0。


    //初始化IO 串口1
    //pclk2 CLK2时钟频率(Mhz)
    //bound:波特率
    void uart_init(u32 pclk2。u32bound)
    {
    floattemp;
    u16mantissa;
    u16fraction;
    temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
    mantissa=temp;
    //得到整数部分
    fraction=(temp-mantissa)*16;//得到小数部分
    mantissa<<=4;
    mantissa+=fraction;
    RCC->APB2ENR|=1<<2;
    //使能PORTA口时钟
    RCC->APB2ENR|=1<<14;
    //使能串口时钟
    GPIOA->CRH=0X444444B4;//IO状态设置
    RCC->APB2RSTR|=1<<14;
    //复位串口1
    RCC->APB2RSTR&=~(1<<14);//停止复位
    //波特率设置
    USART1->BRR=mantissa; // 波特率设置
    USART1->CR1|=0X200C;
    //1位停止,无校验位.
    #ifdef EN_USART1_RX
    //假设使能了接收
    //使能接收中断
    USART1->CR1|=1<<8;
    //PE中断使能
    USART1->CR1|=1<<5;
    //接收缓冲区非空中断使能
    MY_NVIC_Init(3。3。USART1_IRQChannel,2);//组2。最低优先级
    #endif
    }
    从该代码能够看出,其初始化串口的过程,和我们前面介绍的一致先计算得到USART1->BRR的内容。

    然后開始初始化串口引脚。接着把USART1复位,然之后设置波特率和奇偶校验等。
    这里须要注意一点,由于我们使用到了串口的中断接收,必须在usart.h里面定义 EN_USART1_RX 。该函数才会配置中断使能。以及开启串口1的NVIC中断。这里我们把串口1中断放在组2,优先级设置为组2里面的最低。


    再介绍一下串口1的中断服务函数USART1_IRQHandler,该函数的名字不能自定义了,MDK已经给每一个中断都分配了一个固定的函数名,我们直接用就能够了。

    详细这些函数的名字是什么,我们能够在MDK提供的样例里面,找到stm32f10x_it.c,该文件中面包括了STM32全部的中断服务函数。USART1_IRQHandler的代码例如以下:
    void USART1_IRQHandler(void)
    {
    u8res;
    if(USART1->SR&(1<<5))//接收到数据
    {
    res=USART1->DR;
    if((USART_RX_STA&0x80)==0)//接收未完毕
    {
    if(USART_RX_STA&0x40)//接收到了0x0d
    {
    if(res!=0x0a)USART_RX_STA=0;//接收错误。又一次開始
    elseUSART_RX_STA|=0x80;
    //接收完毕了
    }else //还没收到0X0D
    {
    if(res==0x0d)USART_RX_STA|=0x40;
    else
    {
    USART_RX_BUF[USART_RX_STA&0X3F]=res;
    USART_RX_STA++;
    if(USART_RX_STA>63)USART_RX_STA=0;//接收数据错误,又一次開始接收
    }}}}}
    该函数的重点就是推断接收是否完毕,通过检測是否收到0X0D、0X0A的连续2个字节(回车键)来检測是否结束。当检測到这个结束序列之后。就会置位USART_RX_STA的最高为来标记已经收到了一次数据。之后等待外部函数清空该位之后才開始第二次接收。所接收的数据所有存放在USART_RX_BUF里面,一次接收数据不能超过64个字节。否则被丢弃。
    介绍完了这两个函数。我们回到test.c,在test.c里面编写例如以下代码:
    #include <stm32f10x_lib.h>
    #include "sys.h"
    #include "usart.h"
    #include "delay.h"
    #include "led.h"
    #include "key.h"
    //Mini STM32开发板范例代码3
    //串口实验
    //正点原子@ALIENTEK
    //2010.5.28
    int main(void)
    {
    u8t;
    u8len;
    u16times=0;
    Stm32_Clock_Init(9);//系统时钟设置
    delay_init(72);
    //延时初始化
    uart_init(72。9600);
    //串口初始化为9600
    LED_Init();
    //初始化与LED连接的硬件接口
    while(1)
    {
    if(USART_RX_STA&0x80)
    {len=USART_RX_STA&0x3f;//得到此次接收到的数据长度
    printf("n您发送的消息为:n");
    for(t=0;t<len;t++)
    {USART1->DR=USART_RX_BUF[t];
    while((USART1->SR&0X40)==0);//等待发送结束}
    printf("nn");//插入换行
    USART_RX_STA=0;
    }else
    {times++;
    if(timesP00==0)
    {printf("nMiniSTM32开发板
    串口实验n");
    printf("正点原子@ALIENTEKnnn");
    }
    if(times 0==0)printf("请输入数据,以回车键结束n");
    if(times0==0)LED0=!LED0;//闪烁LED,提示系统正在执行.
    delay_ms(10);}}}
    这段代码比較简单,重点看下下面两句:
    USART1->DR=USART_RX_BUF[t];
    while((USART1->SR&0X40)==0);//等待发送结束
    第一句。事实上就是发送一个字节到串口。通过直接操作寄存器来实现的。第二句呢,就是我们在写了一个字节在USART1->DR之后,要检測这个数据是否已经被发送完毕了,通过检測USART1->SR的第6位,是否为1来决定能否够開始第二个字节的发送。



    寄存器:
    1.串口1的时钟使能在APB2ENR寄存器第14位(其它串口的时钟使能位都在APB1ENR)。


    2.串口1的复位是通过配置APB2RSTR寄存器的第14位(其它串口的复位位在APB1RSTR里面)
    3.波特率寄存器USART_BRR(低16位有效)
    4.控制寄存器USART_CR1~3:低14位有效;位13(UE)是串口使能位,位3(TE)是发送使能位,位2(RE)是接受使能位
    5.数据寄存器USART_DR(低9位有效,兼具读写功能)
    6.状态寄存器USART_SR:5位RXNE(读数据寄存器非空)。6位TC(发送完毕)

  • 相关阅读:
    zend guard加密使用方法
    在网页中嵌入任意字体(特殊字体/自定义字体)的解决方案
    lamp一键安装包
    PHP错误“This file has expired”的解决方法
    php采集
    smarty建的mvc环境
    sql语句操作数据库重复数据
    古语:花繁柳密处拨得开,才是手段;风狂雨急时立的定,方显脚跟。
    获取日期的jquery.ui.datepicker
    el表达式简介
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/7019807.html
Copyright © 2011-2022 走看看