历史上的今天
返回首页

历史上的今天

今天是:2024年10月12日(星期六)

正在发生

2019年10月12日 | STM32F1笔记(三)UART/USART

2019-10-12 来源:eefocus

UART:Universal Asynchronous Receiver/Transmitter(通用异步收/发器)


USART:Universal Synchronous/Asynchronous Receiver/Transmitter(通用同步/异步串行收/发器)


从命名即可看出USART就是UART的基础上添加了同步功能。通常把UART/USART称为串口。


串口包含TLL电平和232的串口,485等电气特性的串口。232、485通常应用于工业。


串口配置的一般步骤可以参考正点原子的总结:


1、串口时钟使能,GPIO时钟使能;


2、串口复位;(我不知道这一步的意义,去掉似乎也没影响,求大神指点)


3、GPIO端口模式的配置;


4、串口参数初始化;


5、初始化NVIC并开启中断;


6、使能串口;


7、编写中断服务函数。


配置示例:


void Usart3_Init(unsigned int BaudRate)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    USART_InitTypeDef USART_InitStructure;

    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

    

    USART_DeInit(USART3);

  

    //USART3_TX   GPIOB.10

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

   

    //USART3_RX   GPIOB.11

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

 

    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_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_Rx | USART_Mode_Tx;

 

    USART_Init(USART3, &USART_InitStructure);

    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);

    USART_Cmd(USART3, ENABLE);

}

注意:在此示例中GPIO的速率配置为50M,其实没必要那么高,可降低至2M。速率越高,噪声越大,功耗越高。


在配置代码中,开启了接收中断。在日常串口使用中,都会规定通信协议。通信协议的解析,通常在中断服务函数里进行。


通信协议通常由帧头,数据,帧尾三部分组成。


帧头不正确,不继续处理后续接收到的内容。


帧尾不正确,对数据不进行处理。


示例:

帧头由两部分组成,校验信息和数据长度。示例中断校验信息,赋值给unsigned char的变量,相加后为0。这是特殊的帧头。


    unsigned char chr = 0;

 

    chr += (0xAA + 0xBB + 0xCC + 0xDD + 0xEE + 0x04);

 

    printf("chr=%Xn", chr);

数据长度通常只指数据的长度,不包含帧头校验信息和帧尾的长度。


帧尾可以是CRC等校验方式。可包含长度也可不包含,计算数据的CRC。目的是确保数据的一致性。


串口中断服务函数示例:


void USART3_IRQHandler(void)

{       

    if(USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == SET)

    {

        USART_ClearITPendingBit(USART3, USART_IT_RXNE);

        

        g_usart3_recv_data = USART_ReceiveData(USART3);

        

        switch(g_usart3_recv_state)

        {

            case USART3_RECV_FIRST_FRAME_HEAD:

                if(MKLM_FIRST_FRAME_HEAD == g_usart3_recv_data)

                {

                    g_usart3_recv_state = USART3_RECV_SECOND_FRAME_HEAD;   

                }

                else

                {

                    g_usart3_recv_state = USART3_RECV_FIRST_FRAME_HEAD;             

                }

                break;

            

            case USART3_RECV_SECOND_FRAME_HEAD:

                if(MKLM_SECOND_FRAME_HEAD == g_usart3_recv_data)

                {

                    g_usart3_recv_state = USART3_RECV_FIRST_LENGTH;

                }

                else

                {

                    g_usart3_recv_state = USART3_RECV_FIRST_FRAME_HEAD;             

                }

                break;

                

            case USART3_RECV_FIRST_LENGTH:

                g_Usart3_recv_struct.length = g_usart3_recv_data;

                g_Usart3_recv_struct.length <<= 8;

                g_usart3_recv_state = USART3_RECV_SECOND_LENGTH; 

                break;

            

            case USART3_RECV_SECOND_LENGTH:

                g_Usart3_recv_struct.length |= g_usart3_recv_data;

                g_usart3_recv_length = 0;

                g_usart3_recv_state = USART3_RECV_ADDRESS; 

                break;

            

            case USART3_RECV_ADDRESS:

                g_Usart3_recv_struct.address = g_usart3_recv_data;

                g_usart3_recv_length++;

                g_usart3_recv_state = USART3_RECV_ORDER;

                break;

            

            case USART3_RECV_ORDER:

                g_Usart3_recv_struct.order = g_usart3_recv_data;

                g_usart3_recv_length++;

                g_usart3_recv_state = USART3_RECV_ACTION; 

                break;

            

            case USART3_RECV_ACTION:

                g_Usart3_recv_struct.action = g_usart3_recv_data;

                g_usart3_recv_length++;

                g_usart3_recv_state = USART3_RECV_FIRST_CRC;

                break;

            

            case USART3_RECV_FIRST_CRC:

                g_Usart3_recv_struct.crc16 = g_usart3_recv_data;

                g_Usart3_recv_struct.crc16 <<= 8;

                g_usart3_recv_length++;

                g_usart3_recv_state = USART3_RECV_SECOND_CRC;

                break;

            

            case USART3_RECV_SECOND_CRC:

                g_Usart3_recv_struct.crc16 |= g_usart3_recv_data;

                g_usart3_recv_length++;

            

                if(g_usart3_recv_length == g_Usart3_recv_struct.length)

                {

                    g_recv_status = RECEIVE_OK;

                }

                else 

                {

                    g_recv_status = RECEIVE_LENGTH_ERROR;

                }

                                    

                g_usart3_recv_flag = USART3_RECV_SECCESS;

                g_usart3_recv_length = 0;

                g_usart3_recv_state = USART3_RECV_FIRST_FRAME_HEAD;

                break;

            

            default:

                break;

        }

    }

}

 


STM32使用printf的方法。


在魔术棒里勾选Use MicroLIB(默认是不勾选的)


以串口2为例,在串口2相关.c里(可在任何位置,为防混乱放在需要配置给printf的串口文件里)


加入以下代码(别忘了添加包含头文件stdio.h)


#include

 

int fputc(int ch, FILE* stream)

{

    while (!(USART2->SR & USART_FLAG_TXE));

    USART_SendData(USART2, (uint8_t)ch);

    

    return ch;

}

就可以调用printf了,调用前别忘了相关串口要初始化。


Uart2_Init(9600); 

     

while(1)

{

    printf("Hello World!rn");

    delay_ms(100);

}

通过串口助手可以看到现象

推荐阅读

史海拾趣

Dawn Electronics Inc公司的发展小趣事

在快速发展的同时,Dawn Electronics Inc公司始终关注社会责任。公司积极参与公益活动,支持教育、环保等事业。同时,公司还注重环保和可持续发展,采用环保材料和生产工艺,减少对环境的影响。这些举措不仅提升了公司的社会形象,也为公司的长期发展奠定了坚实的基础。

Fabrimex AG公司的发展小趣事

1982年,Fabrimex AG收购了瑞士领先的实验室电源制造商Erlenbach的K. Witmer Elektronik AG博士。这一收购不仅增强了公司在实验室电源领域的实力,还进一步巩固了其在电子行业中的地位。通过整合双方的技术和资源,Fabrimex AG在实验室电源领域取得了更高的市场份额和更广泛的客户认可。

DURABLE公司的发展小趣事

DURABLE公司成立于20世纪90年代初,最初是一家专注于电子材料研发的小型科技公司。在创始人李博士的带领下,DURABLE不断投入研发资金,积极探索新材料在电子行业的应用。经过数年的努力,公司成功开发出一种具有超高耐用性和稳定性的新型电子材料,这一创新为DURABLE赢得了业界的广泛认可。随着技术的不断成熟,DURABLE的产品逐渐应用于智能手机、平板电脑等高端电子产品中,公司的市场份额也逐年攀升。

Anvo-Systems公司的发展小趣事

Anvo-Systems深知人才是企业发展的核心动力。因此,公司一直注重与高校和研究机构的合作,共同开展电子技术的研发与创新。通过与高校合作开展科研项目、设立奖学金等方式,Anvo-Systems吸引了大批优秀的人才加入公司。同时,公司还建立了完善的培训体系,为员工的职业发展提供了有力支持。这些举措不仅提升了公司的研发实力,也为公司的未来发展储备了丰富的人才资源。

Andersen Laboratories Inc公司的发展小趣事

随着LED背光液晶电视市场的快速发展,AnalogicTech敏锐地捕捉到了这一机遇。公司推出了直接式和边缘式LED背光驱动器系列,显著增强了LED背光液晶电视的能效和用户体验。这一创新举措不仅为AnalogicTech赢得了市场份额,也进一步巩固了其在电子行业中的领先地位。

BOT公司的发展小趣事

广西来宾电厂是中国第一个国家正式批准的BOT试点项目。该项目由法国电力国际和通用电气阿尔斯通公司作为项目公司的主要股东,总投资为6.16亿美元。这个电厂的装机规模为72万千瓦,安装了两台36万千瓦的进口燃煤机组。在长达18年的特许经营期内,该项目为广西地区提供了稳定的电力供应,同时也为项目公司带来了可观的投资回报。随着时间的推移,该项目成为了BOT模式在中国成功应用的典范,为后来的类似项目提供了宝贵的经验。

问答坊 | AI 解惑

航空蓄电池野外充放电车的设计与研制

摘要:航空蓄电池野外充放电车的设计与研制,采用电子集成化模块和开发电源技术,使航空蓄电池野外充放电车的功率大、体积小、稳态精度高。通过在航空兵部队的使用,证明移动式综合充放电设备具重要的经济和军事效益。     关键词: ...…

查看全部问答>

MCS-51单片机温度控制系统

本帖最后由 paulhyde 于 2014-9-15 09:17 编辑 MCS-51单片机温度控制系统  …

查看全部问答>

更快进行原型开发的八个技术考虑

转自:NI 概览 为您下一个嵌入式项目或想法创建功能原型系统是得到预算和从高层管理获得批准的重要步骤。在开始原型开发之前,考虑一下您所有需要的工具。另一个需要记住的重要原则是原型开发应该足够快速,不应该在原型系统上花费过多的时间,投 ...…

查看全部问答>

DC-DC buck降压不稳定请教

设计了一个5.0V输入,可调输出buck电路,1.5M固定频率但是在较大电流输出,并直接开关电源的时候,时不时出现不稳定情况不稳定时前几个占空比很大,直至输出电压过高仿真上非常稳定,PM也足够这可能是什么原因造成的?请教各位!…

查看全部问答>

具备图形加速能力的嵌入式应用系统

具备图形加速能力的嵌入式应用系统…

查看全部问答>

在vxWorks系统中如何使用打印机打印

在一个VxWorks操作系统中,如何通过网络驱动网络打印机(如HP LaserJet 5200网络激光打印机)打一份文本文件。 大家可以给出一些启发性的意见。…

查看全部问答>

硬盘分区

硬盘分区问题 我现在的分区不合理 我想重新分 比如我现在的F盘有三十G、 我想再为它加5G 我已经把这个盘中的所有数据转出来了 我加后会不会影响其它盘的数据? 就是把其它盘的数据搞丢? …

查看全部问答>

LPC1343擦除flash问题

烧写了一个程序,JTAG口被禁了,擦除不了,用flash magic也不行。请高手帮忙…

查看全部问答>

【求助】外接4M晶振不起振

我用的是MSP1121的,在XIN和XOUT两端接一个4M晶振。如下设置后,但是就是不起振。 不知道是什么原因? BCSCTL1 |= XTS; // ACLK= LFXT1= 高频晶体振荡器 do { IFG1 &= ~OFI ...…

查看全部问答>