首先,我们看到的开发板单片机上面的一部分灯的电路,本次我们主要以这8个LED展开叙述,灯对应的单片机的引脚是P0口,本章主要以下面四个部分展开,点亮灯,灯闪烁,流水灯,呼吸灯。本章节主要以程序展开,但是硬件原理依然是很重要的一部分。
分析原理图
从原理图上面我们看出来单片机的引脚对应在灯负极,灯正极对应的是电阻然后连接在5V电源上面,所以我们只需要控制单片机的引脚处于低电平即可让灯有压降,从而发光。
课外知识:
这里的电阻是限流作用,红,橙,黄灯的压降一般为1.8-2.2V左右,蓝,绿,白灯压降在2.8-3.6V左右,这样需要选择不一样的限流电阻才能使得灯的电流值稳定在10mA左右,一般灯的额定电流在20mA,但是为了稳定长期使用,我们最好是将灯电流控制在额定电流的一半左右,否则在长期使用后会出现光衰现象,比如电梯的数码管显示1楼会明显比其他的笔端要暗一点,这就是光衰的现象,可以使用程序扫描的形式让灯可以更加长久的稳定工作,有短暂的间歇时间也能让灯寿命更久。
2.1 点亮一个灯
点亮第一个灯,是我们开发程序的最重要的一个过程,也是学习单片机的不可忽视的重要一步,所以在点灯过程我们会讲解的十分详细,这不仅是一个灯发光,而是单片机开发流程的熟悉,对单片机的了解大大增加。
/********************************** 包含头文件 **********************************/ #include <reg52.h> /********************************** PIN口定义 **********************************/ sbit LED=P0^0;//LED1灯触发引脚P0.0 /********************************** 函数名: main 传递参数:无 返回参数:无 函数作用:主函数 **********************************/ void main(void) { LED=0; while(1); }
程序从上向下看
1、包含单片机的头文件
2、PIN口定义
3、主函数
sbit
是单片机中的一个特殊功能寄存器位,用于控制特定的输入/输出引脚。sbit可以被用来声明一个位变量,并将其与特定的引脚相连。sbit的语法格式如下:
sbit <bit_variable_name> = <port_name>^<pin_number>;
其中,<bit_variable_name>
是位变量的名称,<port_name>
是引脚所在的端口名称,<pin_number>
是引脚的编号。通过使用sbit,可以方便地控制单片机的引脚状态,例如设置引脚为输入或输出、读取或写入引脚的状态等操作。
定义引脚之后,我们在主函数初始化中将该引脚设置为低电平即可使得LED发光。
2.2 点亮一个闪烁的灯
/**********************************
包含头文件
**********************************/
#include <reg52.h>
/**********************************
PIN口定义
**********************************/
sbit LED=P0^0;//LED1灯触发引脚P0.0
/**********************************
函数名: usleep
传递参数: ms
返回参数: 无
函数作用: 延时1ms函数
**********************************/
void usleep(unsigned int ms)
{
unsigned int m,n;
for(m=ms;m>0;m--)
for(n=110;n>0;n--);
}
/**********************************
函数名: main
传递参数:无
返回参数:无
函数作用:主函数
**********************************/
void main(void)
{
LED=0;
usleep(500);
LED=1;
usleep(500);
while(1);
}
1.变量定义
变量定义是在程序中声明并分配内存空间给变量,以便在程序中存储和操作数据。
在C/C++中,变量定义的一般语法格式为:
<数据类型> <变量名>;
其中,<数据类型>
表示变量的数据类型,例如int
、float
、char
等;<变量名>
表示变量的名称,可以根据需要自行命名。
2.延时函数
延时函数是在程序中用于暂停一段时间的函数。在C语言中,常用的延时函数是sleep()
和msleep()
函数。
sleep()
函数:sleep()
函数用于让程序休眠指定的秒数。其函数原型为:void sleep(unsigned int seconds);
,其中seconds
参数表示要休眠的秒数。该函数会使程序暂停指定的秒数,然后继续执行后续的代码。msleep()
函数:msleep()
函数用于让程序休眠指定的微秒数。其函数原型为:void msleep(unsigned int microseconds);
,其中microseconds
参数表示要休眠的微秒数。该函数会使程序暂停指定的微秒数,然后继续执行后续的代码。
这两个函数都是阻塞函数,即在休眠期间,程序无法进行其他操作。需要注意的是,sleep()
和msleep()
函数的精度受系统时钟精度和调度器的影响,可能存在一定的误差。
延时函数的使用场景包括但不限于以下几种情况:
- 在需要控制程序执行速度或时间间隔的场景中,可以使用延时函数控制程序的执行速度。
- 在需要模拟实际操作或等待外部事件的情况下,可以使用延时函数暂停程序的执行。
需要注意的是,延时函数的使用应该谨慎,过多或不合理使用延时函数可能会导致程序的响应性下降或出现其他问题。在某些情况下,可能需要使用其他的方式来实现精确的时间控制,如使用定时器或其他高级的时间管理技术。
/**********************************
包含头文件
**********************************/
#include <reg52.h>
/**********************************
PIN口定义
**********************************/
sbit LED=P0^0;//LED1灯触发引脚P0.0
/**********************************
函数名: usleep
传递参数: ms
返回参数: 无
函数作用: 延时1ms函数
**********************************/
void usleep(unsigned int ms)
{
unsigned int m,n;
for(m=ms;m>0;m--)
for(n=110;n>0;n--);
}
/**********************************
函数名: main
传递参数:无
返回参数:无
函数作用:主函数
**********************************/
void main(void)
{
while(1)
{
LED=0;
usleep(500);
LED=1;
usleep(500);
}
}
上面程序可以让灯一直闪烁。
主函数中的 while(1)
是一个无限循环的语句,它会一直执行循环内的代码,直到程序被手动终止或满足某个终止条件。
一般情况下,while(1)
循环用于需要持续执行某个任务或等待某个事件发生的场景。在循环内部,可以编写一系列的语句来完成特定的任务。
以下是一个简单的示例,展示了 while(1)
循环的基本结构:
int main() {
while(1) {
// 循环内的代码
// ...
}
return 0;
}
在实际应用中,循环内的代码可能会包含条件判断、函数调用、变量操作等。循环内的代码可以根据需要进行修改和扩展。
需要注意的是,由于 while(1)
是一个无限循环,如果没有适当的终止条件或手动终止程序,它将一直执行下去,可能导致程序陷入死循环,造成资源浪费或程序无法正常运行。因此,在编写程序时要确保循环内的代码逻辑正确,并且有合适的终止条件。
2.3 流水灯
/**********************************
包含头文件
**********************************/
#include <reg52.h>
/**********************************
PIN口定义
**********************************/
sbit LED1 = P0^0; // 定义LED1连接的IO口
sbit LED2 = P0^1; // 定义LED2连接的IO口
sbit LED3 = P0^2; // 定义LED3连接的IO口
sbit LED4 = P0^3; // 定义LED4连接的IO口
sbit LED5 = P0^4; // 定义LED1连接的IO口
sbit LED6 = P0^5; // 定义LED2连接的IO口
sbit LED7 = P0^6; // 定义LED3连接的IO口
sbit LED8 = P0^7; // 定义LED4连接的IO口
/**********************************
函数名: usleep
传递参数: ms
返回参数: 无
函数作用: 延时1ms函数
**********************************/
void usleep(unsigned int ms)
{
unsigned int m,n;
for(m=ms;m>0;m--)
for(n=110;n>0;n--);
}
/**********************************
函数名: main
传递参数:无
返回参数:无
函数作用:主函数
**********************************/
void main(void)
{
while(1)
{
LED1=0;
usleep(500);
LED1=1;
LED2=0;
usleep(500);
LED2=1;
LED3=0;
usleep(500);
LED3=1;
LED4=0;
usleep(500);
LED4=1;
LED5=0;
usleep(500);
LED5=1;
LED6=0;
usleep(500);
LED6=1;
LED7=0;
usleep(500);
LED7=1;
LED8=0;
usleep(500);
LED8=1;
}
}
上面展示了最为简单的流水灯,但是程序写的就不是很简洁,所以我们不用这样的方式去写本次的流水灯。请继续看下面的程序。
/**********************************
包含头文件
**********************************/
#include <reg52.h>
/**********************************
参数定义
**********************************/
unsigned char LED = 0x01; // 定义LED灯的初始状态,从最低位开始点亮
/**********************************
函数名: usleep
传递参数: ms
返回参数: 无
函数作用: 延时1ms函数
**********************************/
void usleep(unsigned int ms)
{
unsigned int m,n;
for(m=ms;m>0;m--)
for(n=110;n>0;n--);
}
/**********************************
函数名: main
传递参数:无
返回参数:无
函数作用:主函数
**********************************/
void main(void)
{
unsigned char i;
while(1)
{
for(i = 0; i < 8; i++)
{
P0 = ~(LED << i); // 将LED左移i位,并取反后赋值给P1口,实现LED灯的点亮
usleep(500); // 延时一段时间
}
}
}
这是一种可以通过变量LED移位的方式将将灯进行点亮。
在 C 语言中,可以使用位操作符来进行移位操作。C 语言提供了以下位操作符:
- 逻辑左移(Logical Left Shift):
<<
:将操作数的所有位向左移动指定的位数,右侧空出的位用0填充。例如:result = value << n;
,将变量 value 的值左移 n 位后赋值给变量 result。
- 逻辑右移(Logical Right Shift):
>>
:将操作数的所有位向右移动指定的位数,左侧空出的位用0填充。例如:result = value >> n;
,将变量 value 的值右移 n 位后赋值给变量 result。
- 算术右移(Arithmetic Right Shift):
>>
:将操作数的所有位向右移动指定的位数,左侧空出的位用原符号位填充。例如:result = (signed int)value >> n;
,将变量 value 的值右移 n 位后赋值给变量 result。需要注意,对于有符号整数,算术右移会保留符号位。
需要注意的是,移位操作符只能应用于整数类型的变量,不能直接应用于浮点数类型的变量。在进行移位操作时,需要考虑数据类型的长度和符号位的处理,特别是对于有符号整数的算术右移。
以下是一个使用 C 语言进行移位操作的示例代码:
#include <stdio.h>
int main() {
unsigned int value = 10; // 二进制表示为 0000 0000 0000 1010
unsigned int result;
// 逻辑左移
result = value << 2; // 结果为 0000 0000 0001 0100,等于十进制的 40
// 逻辑右移
result = value >> 2; // 结果为 0000 0000 0000 0010,等于十进制的 2
// 算术右移
int signedValue = -10; // 二进制表示为 1111 1111 1111 0110
int signedResult = signedValue >> 2; // 结果为 1111 1111 1111 1101,等于十进制的 -3
return 0;
}
以上示例代码演示了在 C 语言中如何使用位操作符进行移位操作。你可以根据具体的需求和数据类型,使用逻辑左移、逻辑右移或算术右移来实现相应的移位操作。
下面请再看一种通过左右移动的函数去执行。
/**********************************
包含头文件
**********************************/
#include <reg52.h>
#include <intrins.h> //因为要用到左右移函数_crol_(),所以加入这个头文件
/**********************************
参数定义
**********************************/
unsigned char LED = 0x01; // 定义LED灯的初始状态,从最低位开始点亮
/**********************************
函数名: usleep
传递参数: ms
返回参数: 无
函数作用: 延时1ms函数
**********************************/
void usleep(unsigned int ms)
{
unsigned int m,n;
for(m=ms;m>0;m--)
for(n=110;n>0;n--);
}
/**********************************
函数名: main
传递参数:无
返回参数:无
函数作用:主函数
**********************************/
void main(void)
{
unsigned char i;
P0=0xFE;
while(1)
{
for(i=0;i<7;i++) //将led左移一位
{
P0=_crol_(P0,1);
usleep(500);
}
for(i=0;i<7;i++) //将led右移一位
{
P0=_cror_(P0,1);
usleep(500);
}
}
}
上面的方法是我们调用了intrins.h中的左右移动的函数。
关于上述的C语言库里面的文件我们本次不做详细讲解,有兴趣的同学可以看看下面的文章。
2.4 呼吸灯(不用定时器)
/**********************************
包含头文件
**********************************/
#include <reg52.h>
/**********************************
参数定义
**********************************/
unsigned char Time, i;
/**********************************
函数名: usleep
传递参数: ms
返回参数: 无
函数作用: 延时1ms函数
**********************************/
void usleep(unsigned int ms)
{
while(ms--);
}
/**********************************
函数名: main
传递参数:无
返回参数:无
函数作用:主函数
**********************************/
void main(void)
{
while(1)
{
for(Time = 0; Time < 100; Time++)
{
for(i = 0; i < 20; i++)
{
P0 = 0x00;
usleep(Time);
P0 = 0xff;
usleep(100 - Time);
}
}
for(Time = 100; Time > 0; Time--)
{
for(i = 0; i < 20; i++)
{
P0 = 0x00;
usleep(Time);
P0 = 0xff;
usleep(100 - Time);
}
}
}
}
使用延迟函数,在加上for循环完成对呼吸灯的制作。
关于if,for,while等条件判断循环函数的详细讲解,我们可以观看下面文章
主题授权提示:请在后台主题设置-主题授权-激活主题的正版授权,授权购买:RiTheme官网