历史上的今天
返回首页

历史上的今天

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

2021年12月28日 | STM32F103串口1 printf函数的实现

2021-12-28 来源:eefocus

  在单片机中使用最多的通信接口基本就是串口了,说起串口就不得不提串口中最常用的一个函数就是打印函数printf()函数,在上位机上中这个函数直接从库函数中调用就可以了,那么在单片机中这个函数要怎么使用呢?能不能将这个函数和串口1对应起来,当然是有方法的。


  下面就通过代码来演示一下如何在串口1上使用printf()函数的功能。


void uart_init(u32 bound)

{

    //GPIO端口设置

    GPIO_InitTypeDef GPIO_InitStructure;

    USART_InitTypeDef USART_InitStructure;

    NVIC_InitTypeDef NVIC_InitStructure;


    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟


    //USART1_TX   GPIOA.9

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出

    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9


    //USART1_RX   GPIOA.10初始化

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入

    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10


    //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); //根据指定的参数初始化VIC寄存器


    //USART 初始化设置


    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;//无奇偶校验位

    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制

    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式


    USART_Init(USART1, &USART_InitStructure); //初始化串口1

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断

    USART_Cmd(USART1, ENABLE);                    //使能串口1

}


  首先初始化串口1所使用到的端口,将发送引脚设置为推挽输出模式,将接收引脚设置为浮空输入模式。这里串口使用中断来接收数据,所以还需要设置中断优先级,通过NVIC(嵌套向量中断控制器)来设置串口中断的优先级,接下来设置串口的波特率,字长为8位,1位停止位,无奇偶校验位,无硬件数据流控制端口,串口模式设置为收发模式。最后使能串口,并开启中断功能。


  下面编写串口中断函数,用来接收数据


u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.

//接收状态

//bit15, 接收完成标志

//bit14, 接收到0x0d

//bit13~0, 接收到的有效字节数目

u16 USART_RX_STA = 0;     //接收状态标记


void USART1_IRQHandler(void)                //串口1中断服务程序

{

    u8 Res;

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)

    {

        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; //接收数据错误,重新开始接收

                }

            }

        }

    }

}


  接收数据时通过USART_RX_STA变量的最高两位表示接收数据的状态,接收数据以回车换行作为结束位,回车换行对应的数据为0x0D、0x0A,只有这两个数据挨着接收到之后才表示一组数据成功的接收到了,这里使用USART_RX_STA最高两位表示是否接收到了这两个结束标志。


  串口设置好之后,接下来给串口1添加支持printf()函数的代码。


#if 1

#pragma import(__use_no_semihosting)

//标准库需要的支持函数

struct __FILE

{

    int handle;

};

FILE __stdout;

//定义_sys_exit()以避免使用半主机模式

_sys_exit(int x)

{

    x = x;

}

//重定义fputc函数

int fputc(int ch, FILE *f)

{

    while((USART1->SR & 0X40) == 0); //循环发送,直到发送完毕

    USART1->DR = (u8) ch;

    return ch;

}

#endif


  上面的两个函数是固定模式不需要修改,自己需要修改的是fputc()函数,在这个函数中将寄存器设置为串口1的寄存器,这样printf()函数在打印数据的时候,就会通过串口1将数据发送出去,如何这里的寄存器设置为了其他串口的寄存器,那么使用printf()函数打印的时候就会通过其他串口打印出去。重定义函数fputc()设置好之后,就可在程序中直接使用printf()函数打印了。


int main(void)

{

    u8 t;

    u8 len;

    u16 times=0;

    delay_init();       //延时函数初始化

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    uart_init(115200);

    LED_Init();

    while(1)

    {

if(USART_RX_STA&0x8000)

{

    LED1=!LED1;

len=USART_RX_STA&0x3fff; //获取本次接收数据长度

printf("rn您发送的消息为:rn");

for(t=0;t {

USART_SendData(USART1,USART_RX_BUF[t]);//向串口1发送数据

while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送完成 

}

printf("rn");

USART_RX_STA=0;

}

else

{

times++;

if(times%5000==0)

{

printf("串口实验rn");

}

if(times%300==0)

printf("请输入数据,以回车键结束rn");

if(times%30==0)

LED0=!LED0;

delay_ms(10);

}

    }

}


  在主函数中通过printf()打印提示语句,提示用户输入数据。当用户输入数据并以回车换行结束后,串口接收到数据就会将接收到的数据直接打印出来。

image.png?imageView2/2/w/550

  这样在单片机中,通过串口1就可以输出printf()函数打印的数据了。

推荐阅读

史海拾趣

Elprotronic Inc.公司的发展小趣事

随着公司业务的不断发展壮大,Elprotronic Inc.开始实施国际化战略。他们积极开拓海外市场,与全球众多知名电子厂商建立了长期稳定的合作关系。为了更好地服务海外客户,公司还成立了专业的海外销售和技术支持团队,提供及时、高效的服务。通过国际化战略的实施,Elprotronic Inc.不仅拓展了业务范围,也提升了公司的国际竞争力。

Carlisle Interconnect Components公司的发展小趣事

在电子行业快速发展的背景下,Carlisle Interconnect Components公司始终将技术研发和持续创新作为公司发展的核心动力。公司投入大量资源用于研发新型连接器技术,不断推出具有更高性能、更小型化、更智能化的产品。这些创新产品的问世,不仅为公司带来了更多的市场机遇,更推动了整个电子连接器行业的进步。

COILCRAFT公司的发展小趣事

多年来,COILCRAFT公司凭借其卓越的产品质量、创新能力和良好的服务赢得了广泛的赞誉。在电子行业中,COILCRAFT已经成为高性能磁性元件设计、制造和分销领域的知名品牌。许多知名企业都选择与其合作,共同推动电子行业的发展。同时,COILCRAFT还积极参与行业交流和合作,为推动行业的进步贡献自己的力量。

以上这些故事只是COILCRAFT公司发展历程中的一部分,它们共同展示了这家公司在电子行业中的成长与壮大。未来,随着科技的不断发展和市场需求的不断变化,COILCRAFT将继续保持创新精神,为客户提供更优质的产品和服务。

Custom Electronics Inc公司的发展小趣事

在全球环保意识的日益增强下,CEI积极响应国家节能减排的号召,将环保理念融入企业的生产和经营中。公司引进先进的环保设备和技术,优化生产工艺流程,减少能源消耗和废弃物排放。同时,CEI还倡导绿色消费和循环经济理念,推动电子行业的绿色发展和可持续发展。

请注意,以上故事仅为基于一般情况和假设情境的概述,并非CEI公司的实际发展历程。如有需要,建议查阅相关文献资料或咨询行业专家以获取更准确的信息。

HN Electronic Components GmbH & Co Kg公司的发展小趣事

背景:HN Electronics成立于20世纪90年代初,正值全球电子市场快速崛起的时期。公司由一群在半导体领域拥有丰富经验的工程师创立,他们看到了智能手机和消费电子产品市场的巨大潜力。

发展:初期,HN Electronics专注于研发高性能的电源管理芯片,通过技术创新解决了当时市场上存在的能效低、发热量大等问题。公司迅速获得了业界的认可,并与几家知名手机制造商建立了合作关系。

关键事件:1995年,HN Electronics成功推出其首款自主研发的电源管理芯片,该产品迅速成为市场热销产品,为公司赢得了第一桶金。

ABECO公司的发展小趣事

随着业务的发展,ABECO在1970年做出了一个大胆的决定——进军马耳他市场。这一决策既带来了挑战,也带来了机遇。公司需要适应新的市场环境,了解当地的需求和文化。经过一段时间的摸索和努力,ABECO凭借其高品质的产品和专业的服务,成功在马耳他市场打开了局面,为后续的发展奠定了坚实的基础。

问答坊 | AI 解惑

常见传感器资料

本帖最后由 paulhyde 于 2014-9-15 03:35 编辑 在电子设计竞赛中,肯定少不了各种传感器的应用。下面我将传感器的资料收集如下。希望能够帮到大家。多多提出疑问和意见,大家共同讨论!  …

查看全部问答>

wang1jin带您从零学PCB设计8小时视频教程下载地址

wang1jin带你从零学PCB设计8小时视频教程 原创者:wang1jin 纳米盘下载,请大家下载前装一个纳米工具。再进行下载。 如果文件不能下载请联系wang1jin@126.com。 本视频教程欢迎大家免费传播,供大家学习使用。但不能用于赢取私利,如果有什 ...…

查看全部问答>

求可以和keil联合仿真的Proteus版本

请给出keil版本和Proteus版本以及下载地址,最好可以有怎么使用的具体操作步骤 另外Proteus要有破解的,我下了几次都没有破解文件而不能用 网上给的教程版本不一样,把我都搞晕了…

查看全部问答>

新手上路 skyeye模拟内核移植bootloader能用VIVI么?

老师留得思考题  没人鸟他 但我想尝试下    高手帮帮忙好吗?? 前不久用的u-boot 进行了一次内核移植 (用skyeye模拟的) 不知道 用vivi怎么来 在vivi文件夹内写 skyeye.conf要注意什么啊?? 谢谢了啊!!!…

查看全部问答>

请教关于FLASH

各位大侠:     我的板子现在是用的32M的nor flash : rc28f256j3c ,没有nand flash 由于FLASH太小,想换成一个64M的nor flash :rc28f256p33 我看目前的BSP---driver中并没有关于NOR flash的驱动 只有在eboot中有这样两个函数是关于FL ...…

查看全部问答>

在手机上使用的嵌入式office软件除了quickoffice还有其他的吗?

在手机上使用的嵌入式office软件除了quickoffice还有其他的吗?哪位大侠知道请回答一下。…

查看全部问答>

求OrCAD 原理图仿真技巧

;P ;P ;P [ 本帖最后由 ch0721 于 2010-11-30 00:10 编辑 ]…

查看全部问答>

uart2

各位高手: 我想请教下大家,我想使用omapl138(合众达产品)的uart2 我应该如何修改arm Linux 内核的配置? (能通过测试 使示波器看到波形)…

查看全部问答>

LinUx系统问题

菜鸟问下各位大师怎么查看cpU和操作系统的位…

查看全部问答>

求大神 求帮忙 数控直流电源设计

本帖最后由 paulhyde 于 2014-9-15 03:26 编辑 设计内容:1电路原理图2元件清单3实物制作4设计报告设计要求:1输出电压:范围0-9.9V,步进0.1V2纹波不大于10mV3输出电流:500mA4输出电压值由数码管显示  求大神 求帮忙  感激不尽  有 ...…

查看全部问答>