流水灯相信大家都不陌生吧,百度get到(流水灯是若干个灯泡依次点亮,视觉上感觉到灯光在流动就叫做流水灯。),就流水灯也太简单了吧,但是我想分享的是多种方式操作流水灯,例如P0,P1,P2,P3口都可以用来接LED灯。
下面我会分别使用这个四个口来操作流水的,使用不同的方式实现,其中不乏有最简单的直接付给低电平,也有使用指针来操作LED灯的控制码。相对来说还是很简单的,不多说了,来看代码。
#include
#include //左移函数头文件
/***********************/
typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;
typedef unsigned char u8;
/***********************/
#define led P1
/****************************************************************
***************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1 时,大约延时 10us
*****************************************************************
**************/
void delay(u16 i)
{
while(i--);
}
/***********************/
void main()
{
u8 i;
led=~0x01;//0x01取反即为 0xFE
delay(50000); //大约延时 450ms
while(1)
{
for(i=0;i<7;i++)
{
P1=_crol_(led,1);//将 led 左移一位
delay(50000);
}
for(i=0;i<7;i++)
{
P1=_cror_(led,1);//将 led 右移一位
delay(50000);
}
}
}
这里先解释一下什么是控制码,简单来说我们需要点亮LED灯就需要给这个灯输低电平。然而代码中我们一般用16进制数来表示二进制数,当芯片去读这个16进制数会自动转换从二进制。
例如
unsigned char code Tab[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
0xfe 转化成二进制就是 1111 1110 低位为0这样第一个灯就会亮
#include
#include //左移函数头文件
/***********************/
typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;
typedef unsigned char u8;
/***********************/
#define led P1
#define led P3
/****************************************************************
***************
* 函 数 名 : delay
* 函数功能 : 延时函数
*****************************************************************
**************/
void delay(u16 i)
{
while(i--);
}
void main(void){
while(1){
P3 = 0xfe ; //16 进制转换为二进制 1111 1110 第一个灯点亮,下面同理
delay(2000);
P3 = 0xfd ; //1111 1101
delay(2000);
P3 = 0xfb ; //1111 1011
delay(2000);
P3 = 0xf7;
delay(2000);
P3 = 0xef;
delay(2000);
P3 = 0xdf;
delay(2000);
P3 = 0xbf;
delay(2000);
P3 = 0x7f;
delay(2000);
}
}
#include
//#include //左移函数头文件
/***********************/
typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;
/***********************/
#define led P1
/****************************************************************
***************
* 函 数 名 : delay
* 函数功能 : 延时函数
*****************************************************************
**************/
void delay(u16 i)
{
while(i--);
}
/***********************/
void main()
{
unsigned char i;
while(1){
P1 = 0xff;
delay(200000);
for(i = 0;i<8;i++){
P1 = P1>>1;//将0xff右移动以为高位就变成0 低电平LED 灯亮
//1111 1111 右移动一位后就变成0111 1111
delay(20000);
}
}
}
这个写法其实是多余的,就是用的循环方式不同而已,见谅。
#include
#include //左移函数头文件
/***********************/
typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;
/***********************/
#define led P3
/****************************************************************
***************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1 时,大约延时 10us
*****************************************************************
**************/
void delay(u16 i)
{
while(i--);
}
void main(void){
do
{
P3 = 0xfe ; //16 进制转换为二进制 1111 1110 第一个灯点亮,下面同理
delay(2000);
P3 = 0xfd ; //1111 1101
delay(2000);
P3 = 0xfb ; //1111 1011
delay(2000);
P3 = 0xf7;
delay(2000);
P3 = 0xef;
delay(2000);
P3 = 0xdf;
delay(2000);
P3 = 0xbf;
delay(2000);
P3 = 0x7f;
delay(2000);
}while(1);
}
这种使用将控制码放在数组中的方式就会让代码显得很优雅,嘻嘻。
#include
/***********************/
typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;
#define led P0
/****************************************************************
***************
* 函 数 名 : delay
* 函数功能 : 延时函数
*****************************************************************
**************/
void delay(u16 i)
{
while(i--);
}
void main(void){
unsigned char i;
unsigned char code Tab[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
while(1){
for(i = 0;i<8;i++){
P0 = Tab[i];
delay(2000);
}
}
}
使用指针的优势恐怕现在是不能凸显出来,如果对比的同学应该知道正确使用指针后代码执行数度贼快,哈哈哈。
#include
/***********************/
typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;
#define led P0
/****************************************************************
***************
* 函 数 名 : delay
* 函数功能 : 延时函数
*****************************************************************
**************/
void delay(u16 i)
{
while(i--);
}
void main(void){
unsigned char i;
unsigned char code Tab[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsigned char *P[] = {&Tab[0],&Tab[1],&Tab[2],&Tab[3],&Tab[4],&Tab[5],&Tab[6],&Tab[6],&Tab[7]};
while(1){
for(i = 0;i<8;i++){
P0 = *P[i];
delay(2000);
}
}
}
这个要仔细看就会发现和上面第6种方法的区别,指针在数组种的使用方法有很多种。
#include
/***********************/
typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;
#define led P0
/****************************************************************
***************
* 函 数 名 : delay
* 函数功能 : 延时函数
*****************************************************************
**************/
void delay(u16 i)
{
while(i--);
}
void main(void){
unsigned char i;
unsigned char code Tab[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//流水灯控制码
unsigned char *P
P = Tab;
while(1){
for(i = 0;i<8;i++){
P0 = *(p+i);//*(p+i)相当于a[i],通过指针引用数组元素
delay(2000);
}
}
}
这里就是用函数来操作控制码,毕竟模块化编程还是需要了解的。
#include
/***********************/
typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;
#define led P0
/****************************************************************
***************
* 函 数 名 : delay
* 函数功能 : 延时函数
*****************************************************************
**************/
void delay(u16 i)
{
while(i--);
}
void led_flow(unsigned char *p){
unsigned char i;
while(1){
for(i = 0;i<8;i++){
P0 = *(p+i);//*(p+i)相当于a[i],通过指针引用数组元素
delay(2000);
}
}
}
void main(void){
unsigned char code Tab[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//流水灯控制码
unsigned char *P;
P = Tab;
led_flow(p);//调用函数传入指针
}
以上就是我总结的关于流水灯的操作方式,可能代码中会有小错误,但是相信都开始学单片机的同学还是有一定的编程能力,一定能找出我写的bug哈哈哈。