如何用单片机控制LED小灯闪烁起来,51单片机制作呼吸灯

只是将信息输出到终端,终端不一定必须是屏幕,也可以是其他字符设备,比如一般单片机都会有的串口外设。函数将单片机内部的信息传递给电脑了,但是既然是“交互”,就应该还能把电脑端的信息传递给单片机才行。接下来,将使用本节介绍的交互模块,目的是能够通过电脑控制单片机,决定单片机的动作。

如何用单片机控制LED小灯闪烁起来,51单片机制作呼吸灯

微控制器缺乏交互

然而,当我们制作这两段小灯时,当我们将C语言编写的控制程序编写到单片机中后,我们就无法再控制小LED灯了。 换句话说,“只能看不能动”。 交互性比较差。 在接下来的两节中,将介绍一种交互方法。 目的是将C语言控制程序编入单片机中,仍然能够从外界控制小LED灯。

既然要实现交互,单片机就必须能够捕捉外界的变化。 最简单的方法是按下按钮。 不过,这里我们不打算使用按钮,而是通过“输入命令”来控制LED灯。使用printf将单片机内部的信息传输到计算机

在一般的软件开发中,如果想要检查某个变量的值或者输出提示信息,可以直接使用printf将信息输出到屏幕上。 当一个分支进程需要外部选择时,我们只需要按键盘即可。 但是对于51单片机,如何向它输入命令呢? 我的 51 微控制器既没有屏幕也没有键盘:

如何用单片机控制LED小灯闪烁起来,51单片机制作呼吸灯

事实上,printf只是将信息输出到终端。 终端不一定是屏幕,还可以是其他字符设备,例如微控制器中常见的串行端口外设。 因此,没有屏幕的51单片机也可以使用printf函数,只需要将其输出端口重定向到串口即可。

keil4的重定向工作已经完成。 剩下的工作我们需要做的只是配置单片机的串口寄存器。 这项工作非常简单。 C语言代码可以写成如下,请参见:

void init_uart(unsigned int baud)
{
 SCON = 0x5a;
 TMOD = 0x20;
 TH1 = TL1 = -(FOSC/12/32/baud);
 TR1 = 1;
 ES = 1;
 EA = 1;
}

其中,FOSC是单片机的晶振频率。 我使用的微控制器的频率是11.0592MHz。 现在包含“stdio.h”头文件以使用 printf 函数:

#include "reg51.h"
#include "stdio.h"
void main()
{
 init_uart(9600);
 printf("hello world, num: %dn", 98);
 while(1);
}

编译程序烧录到单片机中,打开电脑中的串口调试软件,发现字符串是正确的,但是C语言程序明明要传输98,但是串口工具上显示的数字电脑是25088!

如何用单片机控制LED小灯闪烁起来,51单片机制作呼吸灯

这个问题可能是因为我使用的微控制器是8位的。 解决问题的方法其实在keil帮助文件中提到过:

如何用单片机控制LED小灯闪烁起来,51单片机制作呼吸灯

可以使用格式字符“%bd”代替“%d”,也可以强制将数字输出为int类型:

...
 printf("hello world, num: %bdn", 98);
 printf("hello world, num: %dn", (int)98);
...

再次编译编程,发现输出正常。

如何用单片机控制LED小灯闪烁起来,51单片机制作呼吸灯

将信息传递给微控制器

以后你可以使用printf函数将单片机内部的信息传输到计算机中,但既然是“交互式”的,那么你也应该能够将计算机中的信息传输到单片机中。 那么,如何将信息从计算机传输到单片机呢? 其实也可以使用串口。 请看init_uart()函数的代码。 应该可以发现C语言程序已经开启了串口中断,所以可以如下编写中断处理程序,请看:

#define MAX_CMD_LEN 32
static bit is_cmd_ready = 0;
static char cmd[MAX_CMD_LEN] = {0};
static unsigned char cmd_len = 0;
void interrupt_uart() interrupt 4
{
 static unsigned char i = 0;
 if(RI){
 RI = 0;
 cmd[i%MAX_CMD_LEN] = SBUF;
 if(cmd[i%MAX_CMD_LEN]=='n'){
 cmd_len = i;
 i = 0;
 is_cmd_ready = 1;
 }else
 i++;
 }
}

如何用单片机控制LED小灯闪烁起来,51单片机制作呼吸灯

当计算机通过串口向单片机发送数据时,串口数据会逐字节放入SBUF中,C语言程序立即进入interrupt_uart()函数。 此时可以使用全局变量cmd来接收串口数据。 我们和计算机约定,发送的每个命令都以换行符“n”结尾,因此当接收到“n”时,可以将 is_cmd_ready 标志设置为 1。

我们常说的“通信协议”实际上是一系列协议。 从这个角度来看,这里所说的“发送的每个命令都以换行符‘n’结尾”实际上属于一种“通信协议”。

也就是说,计算机通过串口发送的命令会自动放入cmd中,因此我们可以定义接收命令的C语言函数如下:

unsigned char get_uart_cmd(char* oCmd)
{
 unsigned char i = 0;
 while(!is_cmd_ready);
 for(i=0;i<cmd_len;i++)
 oCmd[i] = cmd[i];
 is_cmd_ready = 0;
 return cmd_len;
}

如何用单片机控制LED小灯闪烁起来,51单片机制作呼吸灯

该函数将阻塞并等待 is_cmd_ready 标志。 接收到电脑发送的命令后,会通过oCmd发送命令,并返回接收到的命令长度。 现在您可以编写测试程序如下:

void main()
{
 char mycmd[32] = {0};
 init_uart(9600);
 printf("enter a num...n");
 get_uart_cmd(mycmd);
 printf("cmd: %dn", (int)(mycmd[0]));
 printf("enter a string...n");
 get_uart_cmd(mycmd);
 printf("cmd: %sn", mycmd);
 while(1);
}

如何用单片机控制LED小灯闪烁起来,51单片机制作呼吸灯

编译C语言程序并烧录,在电脑上的串口调试工具中会发现如下提示信息:

如何用单片机控制LED小灯闪烁起来,51单片机制作呼吸灯

因为单片机首先需要一个数字,并且命令需要以换行符结尾,所以我勾选了以下选项,点击发送,发现终端输出:

如何用单片机控制LED小灯闪烁起来,51单片机制作呼吸灯

104 正好等于十六进制的 68,然后输入一个字符串:

如何用单片机控制LED小灯闪烁起来,51单片机制作呼吸灯

一切都按预期进行。

将通信模块封装到库中

这一步很简单。 只需要删除my_uart.c文件中的main函数,然后新建一个头文件,如下所示:

如何用单片机控制LED小灯闪烁起来,51单片机制作呼吸灯

以后开发其他功能时,如果需要与电脑交互,只需将这两个文件添加到工程中即可。 接下来,本节介绍的交互模块将用于通过计算机控制单片机,并确定单片机的动作。 例如:

由于篇幅限制,我们将在下一节介绍。

欢迎在评论区一起讨论、提问。 文章均为手写、原创。 他们每天深入浅出地介绍C语言、Linux等嵌入式开发。 如果你喜欢我的文章,就关注吧,你可以看到最新的更新和往期文章。

单片机

两款单片机STM3232FF103103ZETZET6407IG为主

2024-2-8 23:00:55

单片机

单片机的应用属于芯片级应用,你知道吗?

2024-2-9 0:01:31

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索