暂时先写一些程序,具体分析后面更新、
点亮led灯
1.位移法
#include <reg51.h>
typedef unsigned int uint;
typedef unsigned char uchar;
#define led P2
void delay(uint z);
void main()
{
uint led_b = 0xfe;//11111110
uint led_t;
int i = 0;
led_t = led_b;
while(1)
{
led = led_b;
for(i = 0; i < 8; i++)
{
led = led<<1;
delay(500);
}
}
}
void delay(uint z)
{ uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/* #include "reg51.h" */
#include "reg51.h"
typedef unsigned int uint;
typedef unsigned char uchar;
#define led P2
void delay(uint z);
void main()
{
uint i,temp;
while(1)
{
temp=0xfe;
led=temp;
for(i=0;i<8;i++)
{
delay(1000);
temp<<=1;
temp|=0x01;
led=temp;
}
}
}
void delay(uint z)
{ uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
2.数组法
#include "reg51.h"
typedef unsigned int uint;
typedef unsigned char uchar;
#define led P2
void delay(uint z);
uchar code Tab[]={
0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
void main()
{
uint i;
while(1)
{
for(i = 0; i < 8; i++)
{
led=Tab[i];
delay(1000);
}
}
}
void delay(uint z)
{ uint x,y;
for(x = z; x > 0; x--)
for(y=110;y>0;y--);
}
双灯
1.数组法
#include <reg51.h>
#define led P2
typedef unsigned int uint;
typedef unsigned char uchar;
void delay(uint z);
uchar code Tab [] =
{
0x03,//0000 0011
0x06,//0000 0110
0x0c,//0000 1100
0x18,//0001 1000
0x30,//0011 0000
0x60,//0110 0000
0xc0,
0x81
};
void main()
{
uint i = 0;
while(1)
{
led = 0x00;
for(i = 0; i < 7; i++)
led = Tab[i];
}
}
void delay(uint z)
{
uint x,y;
for(x=z; x>0; x--)
for(y=110; y>0; y--);
}
2.函数法
#include "reg51.h"
#include "intrins.h"//左移右移函数所在库
typedef unsigned char uchar;
typedef unsigned int uint;
#define led P2
void delay(uint z);
void main()
{
uint i;
while(1)
{
led=0x03;
delay(1000);
for(i=0;i<7;i++)
{
led=_crol_(led,1);//左移函数
//led|=0x03;
delay(1000);
}
}
}
void delay(uint z)
{ uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
使用138译码器实现数码管的循环显示数字
相向三灯流水加按键
#include <reg51.h>
#define led_2 P2
#define led_1 P1
sbit key=P3^1;
typedef unsigned int uint;
typedef unsigned char uchar;
void delay(uint z);
int main()
{
uint i = 0;
led_2 = 0x07;//0000 0111
led_1 = 0xe0;//1110 0000
while(1)
{
if(!key)//按下
{
delay(50);//消抖
if(!key)
{
led_1 = 0x00;//P1全灭
while(!key);
}
}
led_2 = 0x07;//0000 0111
led_1 = 0xe0;//1110 0000
delay(1000);
for(i = 0; i < 7; i++)
{
led_2 = led_2 << 1;
led_1 = led_1 >> 1;
delay(1000);
}
}
}
void delay(uint z)
{
uint x = 0, y = 0;
for(x = z; x>0; x--)
for(y = 110; y>0; y--);
}
使用两个独立按键实现十进制的加减,并在数码管上显示,然后再使用一个独立按键实现二进制和十进制的转换。
#include<reg51.h>
/*
十进制和二进制的转换
*/
typedef unsigned char uchar;
typedef unsigned int uint;
sbit SLA=P2^2;
sbit SLB=P2^3;
sbit SLC=P2^4;
sbit k_p = P3^1;
sbit k_m = P3^0;
sbit k_t = P3^2;
void delay(int z);
uchar code Tab[]=
{
0x3f,
0x06,
0x5b,
0x4f,
0x66,
0x6d,
0x7d,
0x07,
0x7f,
0x6f,
0x7d,//a
0x7c,//b
0x39,//c
0x5e,//d
0x79,//e
0x71//f
};
int a[5] = {0};
void main()
{
int num = 0, num2 = 0;
int i, j;
int flag = 1;
while(1)
{
i = 0, num2 = 0;
//按下加按键
if(k_p == 0)
{
delay(10);
if(k_p == 0)
{
num++;
}
while(!k_p);
}
//按下减按键
if(k_m == 0)
{
delay(10);
if(k_m == 0)
{
num--;
}
while(!k_m);
}
//按下转换按键
if(k_t == 0)
{
delay(10);
if(k_t == 0)
{
flag = !flag;
}
while(!k_t);
}
//使得num的值是正确的
if(num > 15)
num = 0;
if(num < 0)
num = 15;
//将num的值传给num2然后后面让num2 做除k取余法求得二进制
num2 = num;
if(flag == 1)
{
P0 = 0x00;
SLA=0,SLB=0,SLC=0;
P0 = Tab[num];//显示十进制
}
else
{
P0 = 0x00;
for(i = 0;i < 5; i++)
a[i] = 0;
i = 0;
while(num2 != 0)
{
a[i++] = num2%2;
num2/=2;
}
for(i=0; i<4; i++)
{
switch(i)
{
case (0):
SLA=0,SLB=0,SLC=0,P0=Tab[a[0]];
break;
case (1):
SLA=1,SLB=0,SLC=0,P0=Tab[a[1]];
break;
case (2):
SLA=0,SLB=1,SLC=0,P0=Tab[a[2]];
break;
case (3):
SLA=1,SLB=1,SLC=0,P0=Tab[a[3]];
break;
}
j = 10;
while(j--);
P0=0x00;
}
}
}
}
void delay(int z)
{
int x, y;
for(x = 0; x < z; x++)
for(y = 0; y < 110; y++);
}
蜂鸣器
#include <reg52.h>
sbit beep=P1^5;
typedef unsigned char u8;
typedef unsigned int u16;
void delay(u16 i)
{
while(i--);
}
void main()
{
while(1)
{
beep=~beep;//产生脉冲 高低交替变化
delay(50);//延时以产生一定频率
}
}
LED点阵的对角线程序
#include <reg51.h>
#include <intrins.h>
typedef unsigned char u8;
sbit SRCLK=P3^6; //上升沿触发传送,从高位开始传送
sbit RCLK=P3^5; //上升沿触发
sbit SER=P3^4; //暂时存储一位数据
void delay(u8 x);
void Hc595SendByte(u8 dat);
void main()
{
while(1)
{
Hc595SendByte(0x80); //1000 0000
P0=0x7f ; //0111 1111
delay(10);
P0=0xFF;
Hc595SendByte(0x40); //0100 0000
P0=0xbf ; //1011 1111
delay(10);
P0=0XFF;
Hc595SendByte(0x20); //0010 0000
P0=0xdf ; //1101 1111
delay(10);
P0=0XFF;
Hc595SendByte(0x10); //0001 0000
P0=0xef ; //1110 1111
delay(10);
P0=0XFF;
Hc595SendByte(0x08); //0000 1000
P0=0xf7 ; //1111 0111
delay(10);
P0=0XFF;
Hc595SendByte(0x04); //0000 0100
P0=0xfb ; //1111 1011
delay(10);
P0=0XFF;
Hc595SendByte(0x02); //0000 0010
P0=0xfd ; //1111 1101
delay(10);
P0=0XFF;
Hc595SendByte(0x01); //0000 0001
P0=0xfe ; //1111 1110
delay(10);
P0=0XFF;
}
}
void delay(u8 x)
{
while(x--);
}
void Hc595SendByte(u8 dat)
{
u8 a;
SRCLK=0; //为了后来有上升沿信号,此时拉低
RCLK=0; //为了后来有上升沿信号,此时拉低
for(a=0;a<8;a++)
{
SER=dat>>7; //SER存储dat的最高位
dat<<=1; //每次向左移一位
SRCLK=1; //上升沿触发
_nop_(); //inrins.h中的延时函数
_nop_(); //inrins.h中的延时函数
SRCLK=0; //为了后来有上升沿信号,将其拉低
}
RCLK=1; //产生上升沿信号
_nop_();
_nop_();
RCLK=0; //为了后面的上升沿信号而拉低
}
红外通信
#include "reg51.h"
#include "intrins.h"
typedef unsigned char u8;
typedef unsigned int u16;
#define LED P2
//10us
void delay(u16 i)
{
while(i--);
}
/*
1.使用红外控制数码管的显示 (完成)
2.同时点亮相应的灯 (完成)
3.让蜂鸣器叫 ()
1.发送功能
2.接收功能
3.解码编码功能
*/
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
//蜂鸣器
sbit beep=P1^5;
u8 code smgduan[17]= {
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0X76
};
sbit IRIN=P3^2;
u8 IrValue[8];
u16 DisplayData[8];
//红外初始化函数(中断0开启函数)
void INIRInit()
{
IT0=1;//下降沿触发
EX0=1;//中断0的开启
EA=1;//总中断的开启
IRIN=1;//处于高电平
}
//数码管显示函数
void Display()
{
u8 i;
for(i = 0; i < 3; i++)
{
switch(i)
{
case 0:
LSC=0,LSB=0,LSA=0;
break;
case 1:
LSC=0,LSB=0,LSA=1;
break;
case 2:
LSC=0,LSB=1,LSA=0;
break;
}
P0=DisplayData[2-i]; //
delay(100);
P0=0x00; //消影
}
}
//led随着不同信号不同的灯亮起
void led(u16 dat)
{
switch(dat)
{
case 0x0c:
LED = 0XFE;
break;
case 0x18:
LED = 0XFD;
break;
case 0x5e:
LED = 0XFB;
break;
case 0x08:
LED = 0XF7;
break;
case 0x1c:
LED = 0XEF;
break;
}
}
void main()
{
/*
1.对于红外线的初始化
2.对于这个数据的解码
3.解码的保存地方
4.数码管显示数据
*/
INIRInit();//此刻的红外线管处于高电平
while(1)
{
LED = 0xff;
DisplayData[0] = smgduan[IrValue[2]/16];
DisplayData[1] = smgduan[IrValue[2]%16];
DisplayData[2] = smgduan[16];
led(IrValue[2]);
Display();
}
}
void ReadIr() interrupt 0
{
u8 i,j;
u16 err;//用于超时检验
u8 Time = 0;
delay(700);//7ms 用于判断信号是否到达
if(IRIN == 0)
{
err = 1000;
//正常情况下是因为IRIN=1而退出循环
//异常则是err =0退出循环
while((IRIN ==0) && (err > 0))
{
delay(1);
err--;
}
if(IRIN == 1)
{
err = 500;
while((IRIN == 1) && (err > 0))
{
delay(1);
err--;
}
//接收程序
for(i = 0; i < 4; i++)
{
//分四组程序
for(j = 0; j < 8; j++)
{
err = 60;
//度过560ms的低电平时间
while((IRIN == 0) && (err > 0))
{
delay(1);
err--;
}
err=500;
while((IRIN == 1) && (err > 0))
{
delay(10);//0.1ms
err--;
Time++;
if(Time > 30)
{
//通信失败
return ;
}
}
IrValue[i]>>=1;
if(Time >= 8)
{
IrValue[i]|=0x80;
}
Time=0;
}
}
}
if(IrValue[2] != IrValue[3])
{
return ;
}
}
}
使用红外控制小灯
/**************************************************************************************
* 红外通信实验 *
实现现象:下载程序后,数码管显示红外遥控键值数据
注意事项: 红外遥控器内的电池绝缘片一定要抽掉
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
#define LED P2
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit IRIN=P3^2;
u8 IrValue[6];
u8 Time;
u8 DisplayData[8];
u8 code smgduan[17]= {
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0X76
};
//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F、H的显示码
/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}
/*******************************************************************************
* 函数名 :DigDisplay()
* 函数功能 :数码管显示函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void DigDisplay()
{
u8 i;
for(i=0; i<3; i++)
{
switch(i) //位选,选择点亮的数码管,
{
case(0):
LSA=0;
LSB=0;
LSC=0;
break;//显示第0位
case(1):
LSA=1;
LSB=0;
LSC=0;
break;//显示第1位
case(2):
LSA=0;
LSB=1;
LSC=0;
break;//显示第2位
}
P0=DisplayData[2-i];//发送数据
delay(100); //间隔一段时间扫描
P0=0x00;//消隐
}
}
/*******************************************************************************
* 函数名 : IrInit()
* 函数功能 : 初始化红外线接收
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void IrInit()
{
IT0=1;//下降沿触发
EX0=1;//打开中断0允许
EA=1; //打开总中断
IRIN=1;//初始化端口
}
void led(u16 dat)
{
switch(dat)
{
case 0x0c:LED = 0XFE;break;
case 0x18:LED = 0XFD;break;
case 0x5e:LED = 0XFB;break;
case 0x08:LED = 0XF7;break;
case 0x1c:LED = 0XEF;break;
}
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
IrInit();
while(1)
{
LED = 0xff;
DisplayData[0] = smgduan[IrValue[2]/16];
DisplayData[1] = smgduan[IrValue[2]%16];
DisplayData[2] = smgduan[16];
led(IrValue[2]);
DigDisplay();
}
}
/*******************************************************************************
* 函数名 : ReadIr()
* 函数功能 : 读取红外数值的中断函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void ReadIr() interrupt 0
{
u8 j,k;
u16 err;
Time=0;
delay(700); //7ms
if(IRIN==0) //确认是否真的接收到正确的信号
{
err=1000; //1000*10us=10ms,超过说明接收到错误的信号
/*当两个条件都为真是循环,如果有一个条件为假的时候跳出循环,免得程序出错的时
侯,程序死在这里*/
while((IRIN==0)&&(err>0)) //等待前面9ms的低电平过去
{
delay(1);//10us
err--;
}
if(IRIN==1) //如果正确等到9ms低电平
{
err=500;
while((IRIN==1)&&(err>0)) //等待4.5ms的起始高电平过去
{
delay(1);
err--;
}
for(k=0; k<4; k++) //共有4组数据
{
for(j=0; j<8; j++) //接收一组数据
{
err=60;
while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
{
delay(1);
err--;
}
err=500;
while((IRIN==1)&&(err>0)) //计算高电平的时间长度。
{
delay(10); //0.1ms
Time++;
err--;
if(Time>30)
{
return;//通信失败强制退出
}
}
IrValue[k]>>=1; //k表示第几组数据
if(Time>=8) //如果高电平出现大于565us,那么是1
{
IrValue[k]|=0x80;
}
Time=0; //用完时间要重新赋值
}
}
}
if(IrValue[2]!=~IrValue[3])
{
return;
}
}
}
外部中断的应用
/******
外部中断0,按下K3过后D1-D7依次亮起,到达D8后会回到D0,如此往复
*****/
#include "reg51.h"
#include "intrins.h"
sbit k3=P3^2;
#define led P2
sbit beep=P1^5;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
unsigned char code smgduan[17]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
};//显示0~F的值
#define TRUE 1
#define FALSE 0
int i =0;
int flag = FALSE;
void delay(unsigned int i)
{
while(i--);
}
void Init0()
{
EA=1;//总中断
EX0=1;//开启中断0
IT0=0;//下降沿触发
}
void main()
{
Init0();
led=0xfe;
while(1);
}
void Int0() interrupt 0
{
int j = 0;
delay(1000);
if(k3 == 0)
{
i++;
led=_crol_(led,1);
// LSA=0;
// LSB=0;
// LSC=0; //控制38译码器的Y0输出低电平
// P0=smgduan[i];
if(i > 7)
{
led=0xfe;
i=0;
}
}
while(!k3);
}
呼吸灯
#include "reg51.h"
sbit PWM=P2^1;
sbit K1=P3^1;
sbit led1=P2^3;
bit DIR;
typedef unsigned int u16;
typedef unsigned char u8;
u16 count, timer, value;
//定时器初始化
void Timer1Init()
{
TMOD|=0x10;
TH1=0XFF;
TL1=0xff;
ET1=1;
EA=1;
TR1=1;
}
void main()
{
Timer1Init();
while(1)
{
if(count > 100)
{
count=0;
if(DIR==1)
{
value++;
}
else if(DIR==0)
{
value--;
}
}
//交换方向
if(value == 1000)
{
DIR=0;
}
if(value == 0)
{
DIR=1;
}
if(timer > 1000)
{
timer=0;
}
if(timer < value)
{
PWM=1;
}
else
{
PWM=0;
}
}
}
void Time1() interrupt 3
{
TH1 = 0XFF;
TL1 = 0xff;
timer++;
count++;
}
使用按键控制蜂鸣器
#include "reg51.h"
sbit beep=P1^5;
sbit K1=P3^1;
sbit K2=P3^0;
typedef unsigned char u8;
typedef unsigned int u16;
u8 flag = 0;
void delay_ms(u8 time)
{
unsigned char a,b,c;
for(c=time; c>0; c--)
for(b=142; b>0; b--)
for(a=2; a>0; a--);
}
void CheckKeys()
{
if(K1 == 0)
{
delay_ms(50);
if(K1 == 0)
flag = 1;
}
if(K2 == 0)
{
delay_ms(50);
if(K2 == 0)
{
flag = 0;
}
}
}
void BeepPlay()
{
u8 i=100;
while(i--)
{
beep=~beep;
delay_ms(1);
}
}
/***************************************************/
/*******功能按下K1蜂鸣器发声,按下K2蜂鸣器停止发声*****/
/***************************************************/
void main()
{
while(1)
{
CheckKeys();
if(flag == 1)
{
BeepPlay();
}
else
{
}
}
}