完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
在单片机应用中,UART串口是个应用简单、广泛的工具。串口可以方便地在单片机之间、单片机与计算机直接进行通信,作为上位机和下位机之间的通信桥梁。下面介绍一些实用的串口应用技巧。 一、如何用串口实现printf输出和scanf输入。 在刚学C语言时,我们常用printf标准打印输出函数输出信息,用scanf来获取用户输入,在单片机上同样可以实现这个功能。需要借助串口终端工具,例如windows的超级终端,或者SecureCRT终端软件。还需要用USB转RS232工具连接电脑和UART串口(注意要电平匹配,单片机是TTL电平,九针RS232串口需要转换成TTL电平后方可与单片机直接连接)。 接下来在单片机程序上,需要配置好串口实现串口输出函数(例如:unsigned char uart_send_byte(unsigned char dat);),要实现printf、scanf功能,则必须有响应的库支持,在keil、iar等集成开发环境都集成了相关库。下面只要我们重写printf依赖的putchar函数和scnaf依赖的getkey函数即可。在任意源(.c)文件里,添加一下内容: #include char putchar (char dat ) { uart_send_byte ( dat ); return dat; } char getkey(void) /* 51单片机为例 */ { while ( !RI ); //等待有数据到来 return SBUF; //返回串口接收的数值 } 在某些编译环境下,putchar的函数原型是int putchar (int);则相应的更改为: int putchar (int dat ) { uart_send_byte ( dat ); return dat; } 如此,便可以在单片机的C程序中使用printf函数和scanf函数了,配合串口终端软件,可以进行调试和交互,值得注意的是,如果想输出换行,在VC环境下只需要printf ( “n” )即可,但是在单片机下需要printf ( “rn” ) 才行。 二、采用中断提高串口效率。 uart打印的波特率常见的有4800、9600、19200、38400、57600、115200,但是对于单片机运行起来而言,耗费的时间是巨大的,例如51单片机常见的串口输出函数是这样写的: voiduart_send_byte( uint8 dat ) { SBUF = dat; while(!ti); //等待发送完成 } 串口输出的时候,以9600的波特率计算,发送100个字符,需要的时间是100ms以上,则MCU的大量时间花费在了while(!TI ) 上了,使得MCU整体效率降低,如何提高串口输出效率?当然有办法,那就是利用串口的中断或者DMA,现介绍中断方式提高输出效率的方法。 在使用中断方式发送数据之前,得先有个数据发送缓冲区,用来存放要发送的数据。缓冲区可以选用环形缓冲区的方式,建立环形缓冲区的方法如下: #defineUART_BUFFER_MAX_LEN 128 //环形缓冲区大小 unsigned charuart_ring_buffer[UART_BUFFER_MAX_LEN]={0};//环形缓冲区数组 unsigned intwrite_pt = 0; //写指针,初始化为0 unsigned intread_pt = 0; //读指针,初始化为0 /* 向环形缓冲区中写一个数据,成功返回0,失败返回1,缓冲区满 */ usnsigned charring_buffer_write ( unsigned char dat ) { If ( write_pt + 1 % UART_BUFFER_MAX_LEN != read_pt ){ //缓冲区有数据 uart_ring_buffer[write_pt++] = dat; write_pt %= UART_BUFFER_MAX_LEN; return 0; }else{ //缓冲区满 return 1; } } /* 向环形缓冲区中读一个数据,成功返回0,失败返回1,缓冲区空 */ unsigned charring_buffer_read ( unsigned char *dat ) { if ( read_pt != write_pt ){ //缓冲区有数据 *dat = uart_ring_buffer[read_pt++]; read_pt %= UART_BUFFER_MAX_LEN; return 0; }else{ //缓冲区空 return 1; } } 以上,一个简单的环形缓冲区就建立起来了。接下来要修改一下串口发送函数和中断服务函数,以51单片机为例,代码如下: unsigned charis_data_null = 1; //定义全局变量,标志是否全部发送 /* 串口发送函数 */ voiduart_send_byte ( uint8 dat ) { if ( is_data_null ){ //如果发送缓冲区空 is_data_null = 0; SBUF = dat; //需要发送一次,用以激活中断 }else{ //如果发送缓冲区非空 while ( ring_buffer_write ( dat ) ); //则写入缓存,如果缓存已满,则等待。 } } /* 串口终端服务函数 */ void uart_isr ()interrupt 4 { unsigned char dat; //临时变量 if ( RI ) { //接收中断 RI=0; //标志位清零 } if( TI ){ //发送中断 TI=0; if ( ring_buffer_read ( &dat ) ){ //如果缓冲区有数据 SBUF = dat; //则发送它 }else{ is_data_null = 0; //否则,标记为空 } } } 这样,就可以使用中断方式进行串口打印输出了。该方法可以很简单移植到其他单片机上。当然,接收部分用中断方式更加常见,建议也使用环形缓冲或者乒乓缓冲的方式接收数据,后面专门介绍环形缓冲和乒乓缓冲的方法,这里暂不做介绍。 串口是单片机开发、嵌入式开发中不可或缺的调试工具,本文介绍的技巧思路很容易移植到其他平台上,用上它,可以调高开发效率,希望我的经验思路能够帮助到你, 以上是我学习和工作中的小小经验和技巧,欢迎更多人能与我互相交流心得。如有不对的地方,欢迎指正批评,我的邮箱(也是QQ账号)是:haowidesky@sina.com。 |
|
|
|
只有小组成员才能发言,加入小组>>
「含关键代码」基于AM3352/AM3354/AM3359的Linux开发案例分享
4880 浏览 0 评论
87375 浏览 0 评论
【高手问答】如何做到精通linux技术?资深工程师带你突破难点
4700 浏览 2 评论
3590 浏览 2 评论
解读Linux :先从创建一个文件夹用来存放jdk压缩文件开始
2465 浏览 0 评论
1976浏览 3评论
这是i.mx6ull的关于usb的宏定义,能解释下这些宏定义的意思
1339浏览 1评论
1246浏览 1评论
求解:aarch64交叉编译工具已经安装成功,环境变量已经配置,怎么将系统架构切换为ARM的架构
1315浏览 0评论
电脑和虚拟机可以互ping,电脑和开发板也可以互ping,但是虚拟机和开发板ping不通是什么原因
1221浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-3 18:54 , Processed in 1.110996 second(s), Total 72, Slave 54 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号