6 8051使用Keil模拟器和调试输出窗口实现串口收发回环
admin
2024-01-18 07:53:24
0
  • 本仓库相关网址:
    CSDN文章地址
    Gitee工程和源码地址

  • 相关仓库:
    嵌入式整体介绍,里面也描述了部分8051的内容:
    才鲸嵌入式 / 嵌入式知识图谱WiKi
    C语言框架讲解,让你对C语言要学哪些东西有一个完整的了解:
    embedded_programming_skills/ 0_doc / 02-C语言框架讲解.md

6)Keil调试输出窗口串口回环

  • 本工程主要演示使用Keil创建一个默认工程,然后添加串口0的回环收发用例,在Keil的调试串口进行串口收发,并且可以使用虚拟串口,通过SSOM32与Keil通信来进行串口收发。

  • 工程文件:本文档同级目录/06_uart0_loopback/06_uart0_loopback.uvproj

  • 将Keil的UART #1调试输出串口与SSCOM32等串口软件绑定的话,需要用到VSPD软件。

  • 参考网址:

    • Keil实例仿真AT89C51串口UART收发数据(附程序)
    • keil MDK 中使用虚拟串口调试串口
    • 虚拟串口 VSPD 的使用
  • 代码展示:

/******************************************************************************** \brief	进行串口0的回环输入输出* \details	可以通过Keil的UART #1调试串口直接输出串口信息和接收串口的输入,*			也可以通过VSPD虚拟串口软件与PC上的SSCOM32等串口软件进行绑定,通过*			串口软件收发信息。* \attention	Keil UART #1和SSCOM32窗口输入的行尾是\r,不是\r\n,*				但是输出又是以\r\n来处理的。Keil模拟器模式下,*				晶振不管设置为多少,UART0不管是否初始化,设置多少波特率,Keil*				UART #1调试串口的收发总是115200的波特率。* \author	将狼才鲸* \date	2022-10-30* \note	参考网址:*			[Keil实例仿真AT89C51串口UART收发数据(附程序)]*			(https://blog.csdn.net/tj_nonstoper/article/details/124271543)*			[keil MDK 中使用虚拟串口调试串口]*			(https://blog.csdn.net/NICHUN12345/article/details/124423615)*			[虚拟串口 VSPD 的使用]*			(https://blog.csdn.net/qq_17351161/article/details/89607458)******************************************************************************//********************************** 头文件 ************************************/
#include 	/* 8051通用的寄存器定义 *//********************************** 宏定义 ************************************/
#define CHAR_LOOPBACK		/* 收到一个字符就返回一个字符 */
//#define STRING_LOOPBACK	/* 收到一行后再返回一行,如果接收buffer满则先返回整个buffer数据 */
/* Keil使用自带的模拟器运行时,输入的换行是\r,但输出换行却是\r\n */
#define FIX_KEIL_EMULATOR_AND_SSCOM32_UART_LINE_FEED_ISSUE#define BUF_MAX_SIZE 16		/* 设置短一点,即使没输入正确的换行符,也能及时有数据返回 *//********************************* 全局变量 ***********************************/
static char rcv_buf[BUF_MAX_SIZE] = {0};	/* 完整的一行接收缓存 */
static int rcv_cnt = 0;	/* 接收的字节数 */
static char rcv_str_end_flag = 0; /* 0 is false, !0 is true */static void uart0_init(void);
static void send_str(char *str);
static void send_char(char c);//如果要使用printf,需要进行putchar输出重定义
//不使用printf,直接往串口写数据也能输出到UART #1
///**
// * \brief		printf重定向的函数,这里重定向到串口0
// * \param[in]	c	承接printf中传入的一个字符
// * \note		这里的函数注释格式是Doxygen,有兴趣的可以自行去了解
// * \return		正常时返回c,错误时返回错误码
// */
//char putchar(char c)
//{
//	ES = 0;				/* 关串口中断 */
//	SBUF = c;           
//	while (TI != 1);	/* 等待发送成功,产生发送中断 */
//	TI = 0;				/* 清除发送中断标志 */
//	ES = 1;				/* 开串口中断 *///	return c;
//}/********************************* 接口函数 ***********************************/
/*** \brief	入口函数*/
int main()
{/* 1. 串口初始化 */uart0_init();/* 2. 打印提示信息 */send_str("====\r\n");send_str("| Check your terminal line end format.\r\n");send_str("| \r \\r \r");send_str("| \n \\n \n");send_str("| \n\r \\n\\r \n\r");send_str("| \r\n \\r\\n \r\n");send_str("====\r\n\r\n");send_str("====\r\n");
#ifdef STRING_LOOPBACKsend_str("Now is string loopback mode\r\n");send_str("Please input string, and end with \\r or \\n.\r\n");
#elsesend_str("Now is char loopback mode\r\n");send_str("Please input char\r\n");
#endif/* 3. 打印从串口中断收到的信息 */while (1) {  	 if (rcv_str_end_flag) {/* 如果收到数据,则进行回环输出 */rcv_str_end_flag = 0;
#ifdef STRING_LOOPBACKsend_str("Your Input: ");send_str(rcv_buf);  /* 把接收到的字符串发送回去 */
#else/* 防止有人不知道串口中断输入是没有回显的,原样输出会以为只是自己的输入 */send_char('>');send_char(rcv_buf[0]);
#	ifdef FIX_KEIL_EMULATOR_AND_SSCOM32_UART_LINE_FEED_ISSUEif (rcv_buf[0] == '\r')send_char('\n');
#	endifsend_char(' ');
#endifrcv_buf[0] = '\0'; /* 清空字符串,直接写个字符串结尾 */}}
}	/********************************* 私有函数 ***********************************/
/*** \brief		串口0初始化* \attention	Keil模拟器模式时可以不初始化,即使配置了参数,也始终以115200波特率输出* \note		不初始化的话能输出数据,但是进不了接收中断,接收不了信息*/
static void uart0_init(void)
{/* 串口参数配置函数,这里配置为9600波特率,1位停止位,8位数据位,无校验 */TMOD = 0x20;  /* Timer1以定时模式工作在方式2:8位常数自动装入定时器/计数器 */SCON = 0x40;  /* SM0 = 0,SM1 = 1,方式1,10位UART "0 D0~D7 1",波特率可变 */REN  = 1;     /* 允许串口接收数据位 *//** \warning 不管设置多少波特率,Keil模拟器在UART #1中的收发始终是115200 */TH1  = 0xFD;  /* 9600波特率:晶振的频率/(12 * (256 - 初值)) = 波特率 * 32 */TL1  = 0xFD;  /* 方式2的TH1,TL1是相等的,TL1自动重装TH1初值 */PCON = 0x00;  /* SMOD = 0波特率不加倍 */IE   = 0x90;  /* 允许总中断,允许串口中断,禁止其他中断 */PS   = 0;     /* 设置串行口中断优先级 */TR1  = 1;     /* 当GATE=0,TR1置“1” 启动定时器1 */
}/*** \brief		发送一个字符* \param[in]	c	发送的字符*/
static void send_char(char c)
{SBUF = c;		/* SBUF是指串行口同地址的两个缓冲寄存器,一个是发送寄存器,一个是接收寄存器,通过读和写来区分 */       while (!TI);		/* 等待一个字符发送完毕 */TI = 0;			/* TI软件清零,等待下一次发送后的置位 */
}/*** \brief		发送一个字符串* \param[in]	str	要发送的字符串指针*/
static void send_str(char *str)
{ES = 0; /* 发送前关闭串口中断,以防发送完每个字符都没必要地进入中断程序 */while (*str != '\0')		/* 持续发送直到字符串结尾 */send_char(*str++);	/* 先取值再自增 */ES = 1; /* 发送完打开串口中断 */
}/*** \brief	串口0中断处理函数* \note	中断默认优先级:0外部中断0 > 1定时/计数器0 > 2外部中断1 > 3定时/计数器1 > 4串行中断*/
void uart0_irq(void) interrupt 4 
{if (RI == 1) {/* RI置位表示一帧数据接收完毕,中断处理后RI必须用软件清0 */RI = 0; /* 中断标志位清零 */ES = 0; /* 关闭串口中断,防止下面程序执行时被打断,防止中断嵌套 */
#ifdef STRING_LOOPBACKif (rcv_cnt < BUF_MAX_SIZE - 2) {/* 接收缓冲区未溢出 */rcv_buf[rcv_cnt] = SBUF; /* 存放1个字节 */if (rcv_buf[rcv_cnt] == '\r' || rcv_buf[rcv_cnt] == '\n') {/* 如果接收到结束符(当前Keil UART #1和SSCOM都是\r) */rcv_str_end_flag = 1;	/* 接收了完整的字符串 */
#ifdef FIX_KEIL_EMULATOR_AND_SSCOM32_UART_LINE_FEED_ISSUErcv_buf[rcv_cnt - 1] = '\n';
#endifrcv_buf[rcv_cnt] = '\0';	/* 在字符串末尾补字符串结束 */rcv_cnt = 0; /* 接收长度清0 */} else {rcv_cnt++;}} else {/* 接收缓冲区溢出 */rcv_str_end_flag = 1;rcv_buf[rcv_cnt] = '\0';rcv_cnt = 0;}
#elsercv_buf[0] = SBUF; /* 存放1个字节 */rcv_str_end_flag = 1;
#endifES = 1;	/* 中断处理完重新打开串口中断 */}
}

相关内容

热门资讯

安卓更改系统语言设置,安卓系统... 你有没有发现,手机里的文字突然变得陌生起来?别担心,这可不是什么外星文字入侵,而是你的安卓手机系统语...
什么安卓系统的平板好用,哪款系... 你有没有想过,拥有一款好用的安卓平板,那感觉简直就像拥有了移动的办公室和娱乐中心呢!市面上平板电脑品...
安卓升级后启动不了系统,原因排... 最近是不是你也遇到了安卓升级后启动不了系统的问题?别急,让我来给你详细说说这个棘手的问题,让你轻松解...
锁住安卓的系统时间,揭秘时间锁... 你有没有发现,有时候手机上的时间总是和你心中的时间不太一样?是不是有时候你明明觉得才过了几分钟,一看...
谷歌安卓系统不及时更新,揭秘不... 你有没有发现,你的安卓手机最近是不是有点儿“懒洋洋”的?更新系统总是慢吞吞的,让人等得花儿都谢了。这...
安卓系统可以修改吗,深度解析可... 你有没有想过,你的安卓手机其实就像一个巨大的宝藏,里面藏着无数可以探索的秘密?没错,我说的就是——安...
安卓系统占用多大运存,揭秘不同... 你有没有发现,手机用着用着,内存就不够用了?尤其是安卓系统,好像总是那么“贪婪”,总是想要更多的运存...
微信鸿蒙系统安卓,微信新生态下... 你知道吗?最近微信在操作系统上又搞了个大动作,那就是鸿蒙系统安卓版。这可是个让人眼前一亮的消息,咱们...
安卓系统自动添加照片,智能捕捉... 你有没有发现,手机里的照片越来越多,有时候翻看相册,竟然发现有些照片是自己都没注意到的!这到底是怎么...
安卓系统发送信息,畅享沟通便捷 你有没有遇到过这种情况?手机里突然弹出一个信息,让你瞬间陷入纠结:是立刻回复,还是假装没看到?今天,...
安卓系统功能机有哪些,探索创新... 你有没有想过,在这个智能机横行的时代,还有一群坚守阵地的小伙伴——安卓系统功能机?它们虽然没有智能手...
安卓几系统怎么看,探究系统生成... 你有没有想过,你的安卓手机里藏着多少秘密?比如,它的系统版本是多少呢?别急,今天就来手把手教你如何查...
修改安卓系统内存占用6,安卓系... 手机用久了是不是感觉越来越卡?别急,今天就来教你怎么修改安卓系统的内存占用,让你的手机焕发第二春!一...
系统文件删除安卓怎么恢复,教你... 手机里的系统文件不小心删掉了,这可怎么办呢?别急,今天就来给你支个招,教你怎么在安卓手机上恢复那些丢...
安卓系统改刷ios系统教程视频... 你有没有想过,把你的安卓手机改刷成iOS系统呢?想象那流畅的操作体验,那独特的苹果风格,是不是瞬间心...
安卓系统慢动作摄影,重温美好时... 你有没有发现,手机拍照已经不能满足我们追求个性的需求了?现在,安卓系统里的慢动作摄影功能,简直就像给...
系统的设计与开发安卓,构建高效... 你有没有想过,为什么你的手机里那么多应用,却总感觉少了点什么?没错,就是那个能让你随时随地掌控一切的...
安卓系统播放器插件,探索安卓系... 你有没有发现,手机里的音乐播放器越来越高级了?这不,最近我发现了几个安卓系统播放器的插件,简直让我爱...
安卓支付系统叫什么名,探索“X... 你有没有发现,现在出门不带钱包也能轻松付款呢?这都得归功于那些神奇的支付系统。说到安卓手机上的支付系...
虚拟卡软件推荐安卓系统,打造个... 你有没有想过,在手机上轻松管理多个账户,同时还能享受便捷的支付体验?这就得靠那些神奇的虚拟卡软件啦!...