从左到右的流水灯的制作(重点)
#include <reg51.h>
#include <intrins.h> //移位函数的头文件
unsigned int j;
void Delay(unsigned int i) // 延时函数
{
while(i--) // 注意这里是i--
{
for(j = 0;j < 120;j++); // 注意这里是120
}
}
void main()
{
P1 = 0xFE;
while(1)
{
P1 = _crol_(0,1); //数据每次左移一位
// crol函数是循环左移函数,即把挪出去的那一位补在后面空的一位
//<<是左移函数,会在空的那一位补0
Delay(100);
}
}
左到右的来回流水灯的制作
#include <reg51.h>
#include <>
void Delay(unsigned int i)
{
while(i--)
{
for(j=0;j<120;j++);
}
}
unsigned int x;
unsigned int y;
void main()
{
P1 = 0xFE;
while(1)
{
for(x=0;x<8;x++)
{
P1 = _crol_(0,1);
Delay(100);
}
for(y=0;y<8;y++)
{
P1 = _cror_(0,1);
Delay(100);
}
}
}
开关量检测指示器
#include <reg51.h>
void Delay(unsigned int i)
{
while(i--)
{
for(int j=0;j<120;j++);
}
}
void main()
{
while(1)
{
if(P1_4 == 0)
{
Delay(20);
while(P1_4==0);
Delay(20);
P1_0 = 0;
}
if(P1_5 == 0)
{
Delay(20);
while(P1_5==0);
Delay(20);
P1_1 = 0;
}
if(P1_6 == 0)
{
Delay(20);
while(P1_6==0);
Delay(20);
P1_2 = 0;
}
if(P1_7 == 0)
{
Delay(20);
while(P1_7==0);
Delay(20);
P1_3 = 0;
}
}
}
单一外中断的应用
#include <reg51.h>
void Delay(unsigned int i)
{
while(i--)
{
for(j=0;j<120;j++);
}
}
void EX0_Init()
{
EA = 1;
EX0 = 1;
IT0 = 1; // 负跳沿触发IT = 1 低电平触发IT = 0
}
void do_EX0() interrupt 0
{
EX0 = 0;
while(1)
{
P1 = 0xF0;
Delay(100);
P1 = 0x0F;
Delay(100);
}
EX0 = 1;
}
void main()
{
P1 = 0x00;
EX0_Init();
while(1);
}
两个外中断的应用
#include <reg51.h>
void Delay(unsigned int i)
{
while(i--)
{
for(j=0;j<120;j++);
}
}
void EX_Init()
{
EA = 1;
EX0 = 1;
EX1 = 1;
IT0 = 1;
IT1 = 1;
IP1 = 1;
IP0 = 1; // 两个中断都设置为高优先级
}
void do_EX0() interrupt 0
{
while(1)
{
P1 = 0xF0;
Delay(100);
P1 = 0x0F;
Delay(100);
}
}
void do_EX1() interrupt 2
{
P1 = 0x00;
}
void main()
{
EX_Init();
while(1)
{
//流水灯代码
}
}
ps:这个代码因为设置了同级中断,所以在进入任何一个中断后,另一个中断不会被响应
中断嵌套(重点)
#include <reg51.h>
void Delay(unsigned int i)
{
while(i--)
{
for(j=0;j<120;j++);
}
}
void EX_Init()
{
EA = 1;
EX0 = 1;
EX1 = 1;
IT0 = 1;
IT1 = 1; // 设置触发方式
IP0 = 0;
IP1 = 1; //设置优先级
}
void do_EX0() interrupt 0
{
while(1)
{
P1 = 0xF0;
Delay(100);
P1 = 0x0F;
Delay(100);
}
}
void do_EX1() interrupt 2
{
P1 = 0x00;
Delay(100);
P1 = 0xFF;
Delay(100);
}
void main()
{
EX_Init();
while(1)
{
//流水灯代码
}
}
多外部中断源系统设计(非重点)
#include <reg51.h>
void EX_Init()
{
EA = 1;
EX0 = 1;
EX1 = 1;
IT0 = 1;
IT1 = 1;
IP0 = 1; // 将外部中断0设置为最高优先级
IP1 = 0;
}
void do_EX0() interrupt 0
{
P1 = 0xFF; // 进入外部中断0,熄灭所有灯
}
void do_EX1() interrupt 2
{
if(P1_0 == 0){P1_4 = 0;}
if(P1_1 == 0){P1_5 = 0;}
if(P1_2 == 0){P1_6 = 0;}
if(P1_3 == 0){P1_7 = 0;}
}
void main()
{
EX_Init();
while(1);
}
P1口外接的8只LED每0.5s闪亮一次
#include <reg51.h>
//计算初值
//公式:定时时间 = (2^16-初值X)*(12/fos) 其中(2^16-初值X)即为TH0和TL0的值
//定时时间为0.5s 也就是5000us 即初值X≈60927
void Timer0_Init()
{
TMOD = 0x01;
TH1 = 60927/256;
TL1 = 60927%256;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void do_Timer0() interrupt 1
{
P1 = ~P1;
TH1 = 60927/256;
TL1 = 60927%256;
}
void main()
{
Timer0_Init();
while(1);
}
计数器的应用(重点)
#include <reg51.h>
void Delay(unsigned int i)
{
while(i--)
{
if(j=0;j<120;j++);
}
}
void Timer1_Init()
{
TMOD = 0x50; //0101 0000
TH1 = 0xFF;
TL1 = 0xFC;
EA = 1;
ET1 = 1;
TR1 = 1;
}
void do_Timer1() interrupt 3
{
while(1)
{
P1 = 0xFF;
Delay(100);
P1 = 0x00;
Delay(100);
}
}
void main()
{
Timer1_Init();
while(1);
}
扩展一个外部中断源(非重点)
#include <reg51.h>
void Timer0_Init()
{
TMOD = 0x06;
TH0 = 0xFF;
TL0 = 0xFF;
ET0 = 1;
TR0 = 1;
TF0 = 0; //溢出标志位清零
}
void main()
{
Timer0_Init();
while(1);
}
在P1.0上产生周期为2ms的方波
#include <reg51.h>
//计算初值
//产生周期为2ms的方波,即要要让P1.0口每1ms翻转一次,所以定时器1需要定时1ms
//定时时间 = (2^16-X)*(12/fos)
//此时的定时时间为1ms,即1000us
// X = 65536-1000
void Timer1_Init()
{
TMOD = 0x10;//0001 0000
TH1 = (65536-1000)/256;
TL1 = (65536-1000)%256;
EA = 1;
ET1 = 1;
TR1 = 1;
}
void do_Timer1() interrupt 3
{
P1_0 = !P1_0;
TH1 = (65536-1000)/256;
TL1 = (65536-1000)%256; //重置初值
}
void main()
{
Timer1_Init();
P1_0 = 0;
while(1);
}
在P1.1上产生周期为1s的方波
多次中断法(推荐)
#include <reg51.h>
//这个题目的定时时间应该是1s/2 = 0.5s 0.5s = 500ms
//定时时间比较长,我们此时采用多次中断的方式来定时
//还是采用定时1的方式1来定时,可以让定时器1一次产生50ms的定时 一共定时10次
//50ms = 50000us
//X = 65536-50000
void Timer1_Init()
{
TMOD = 0x10;
TH1 = (65536-50000)/256;
TL1 = (65536-50000)%256;
EA = 1;
ET1 = 1;
TR1 = 1;
}
unsigned int count;
void do_Timer1() interrupt 3
{
count++;
if(count == 10)
{
count = 0;
P1_1 = !P1_1;
}
TH1 = (65536-50000)/256;
TL1 = (65536-50000)%256;
}
void main()
{
Timer1_Init();
P1_1 = 0;
while(1);
}
双定时器法(不推荐)
T1控制发出1KHZ的音频信号(重点)
#include <reg51.h>
//书上写的计算初值是错误的,以下面注释为准
//产生1KHZ的音频信号,也就是产生音频信号的周期为1ms 所以需要定时的时间为0.5ms
//由0.5ms = 500us 500/1.08 = 460
// X = (65536-460)
void Timer1_Init()
{
TMOD = 0x10;
TH1 = (65536-460)/256;
TL1 = (65536-460)%256;
EA = 1;
ET1 = 1;
TR1 = 1;
}
void do_Timer1() interrupt 3
{
P1_7 = !P1_7;
TH1 = (65536-460)/256;
TL1 = (65536-460)%256;
}
void main()
{
P1_7 = 0;
Timer1_Init();
while(1);
}
测量脉冲宽度——门控位GATEx的应用(非重点)
#include <reg51.h>
unsigned count_high; // 读取TH0
unsigned count_low; // 读取TL0
//最后INT1的正脉冲宽度以机器周期数的形式读入到上面俩变量中
//正脉冲是一个周期信号中高电平的信号
void read_count()
{
do
{
count_high = TH1;
count_low = TL1;
...//可进行显示或其他处理
}while(count_high!=TH1)
}
void main()
{
TMOD = 0x90; // 1001 0000
//需要注意的是:当单片机的GATE为1的时候,如果要打开定时器,除了TR1=1以外还需要INT1=1才可以真正开启定时器
TH1 = 0;
TL1 = 0;
TR1 = 1;
while(P3_3 == 1); //等待P3_3为低电平
TR1 = 1; //P3_3为低电平的时候,TR1=1,但是此时定时器并未被真正开启,还需要INT1=1
while(P3_3 == 0);//等待P3_3为高电平
while(P3_3 == 1); //P3_3为高电平后,真正打开定时器,开始计数
TR1 = 0;
//读取函数
read_count();
}
串口 方式0输出输入(非重点)
例题
#include <reg51.h>
#include <stdio.h>
unsigned char nIndex;
unsigned char nSendByte;
void Delay()
{
static int i = 100;
static int j = 0;
while(i--)
{
for(j=0;j<120;j++);
}
}
void Serial_Init()
{
SCON = 0x00; // 串口为方式0
EA = 1;
ES = 1; // 开启串口中断
}
void dp_Serial() interrupt 4
{
if(TI == 1) //发送中断标志位
{
P1_0 = 1;
Delay();
P1_0 = 0;
nSendByte << 1;
if(nSendByte == 0)
{
nSendByte = 1;
}
SBUF = nSendByte;
}
TI = 0;
RI = 0;
}
void main()
{
Serial_Init();
nIndex = 1;
SBUF = nSendByte;
P1_0 = 0; //使能位
while(1);
}
#include <reg51.h>
unsigned char nRxData;
void Serial_Init()
{
SCON = 0x00;
EA = 1;
ES = 1;
}
void do_Serial() interrupt 4
{
if(RI == 1) //接收到了数据
{
nRxData = SBUF;
}
TI = 0;
RI = 0;
}
void main()
{
while(1)
{
if(P1_0 == 0)
{
P1_1 = 0;
P1_1 = 1;
}
}
}
方式1的应用
#include <reg51.h>
//甲机发送程序
unsigned char temp;
void Serial_Init()
{
PCON = 0x00; // 波特率不倍增
SCON = 0x40; // 0100 0000 SM2位只能在方式二和方式三多机通信
//串口的方式一专门是为了双机通信设置的
TMOD = 0x20;// 0010 0000
TH1 = 0xFD;
TL1 = 0xFD; // 波特率9600
TR1 = 1;
P1 = 0xFF; //P1口输入的时候,需要拉高电平
}
void main()
{
while(1)
{
temp = P1;
SUBF = temp;
//查询方式,无需申请中断
while(TI == 0); //TI = 1 说明一帧数据发送完毕
TI = 0;
}
}
//乙机接收程序
unsigned char temp;
void Serial_Init()
{
PCON = 0x00;
SCON = 0x50;//0101 0000
TMOD = 0x20;//0010 0000
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
}
void main()
{
while(1)
{
//查询方式
while(RI == 0);
RI = 0;
temp = SBUF;
P1 = temp;
}
}
方式2和方式3的应用
#include <reg51.h>
sbit p = PSW_0;
//甲机发送程序
unsigned char Tab[] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; //流水灯显示数据
void Delay()
{
unsigned int i = 100;
unsigned int j;
while(i--)
{
for(j=0;j<120;j++);
}
}
void Serial_Init()
{
SCON = 0xC0;//1100 0000 注意这里的SM2位不需要为1
PCON = 0x00;
TMOD = 0x20;//0010 0000
TH1 = 0xFD;
TL1 = 0xFD; //波特率9600
EA = 1;
ES = 1;
TR1 = 1;
}
void Send(unsigned char data)
{
ACC = data; //把data数据暂存到ACC寄存器中
TB8 = p; //奇偶校验位
SBUF = data; //准备发送数据
while(TI == 0); //等待数据发送
TI = 0;
}
unsigned int count;
void main()
{
Serial_Init();
while(1)
{
for(count=0;count<8;count++)
{
Send(Tab[count]);
Delay(); //等待一段时间再发送
}
}
}
//乙机接收程序
sbit p = PSW_0;
unsigned char Receive()
{
unsigned char data;
while(RI == 0); // 等待接收 查询方式
RI = 0;
ACC = SBUF;
if(RB8 == p) //奇偶校验
{
data = ACC;
return data;
}
}
void Serial_Init()
{
SCON = 0xD0; // 1101 0000 注意这里需要把REN位也置为1
PCON = 0x00;
TMOD = 0x20;
TL0 = 0xFD;
TH0 = 0xFD; //波特率9600
EA = 1;
ES = 1;
TR1 = 1;
}
void main()
{
while(1)
{
P1 = Receive();
}
}
单片机向计算机发送数据(重点)
#include <reg51.h>
unsigned char Tab[] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; //流水灯显示数据
void Send(unsigned char data)
{
SBUF = data;
while(TI == 0); // 等待单片机发送数据结束
TI = 0;
}
void Delay()
{
unsigned int i = 100;
unsigned int j;
while(i--)
{
for(j=0;j<120;j++);
}
}
void Serial_Init()
{
SCON = 0x40;//0100 0000
PCON = 0x00;
TMOD = 0x20;
TH1 = 0xFD;
TL1 = 0xFD; //波特率9600
EA = 1;
ES = 1;//EA和ES可以不写,因为这里用的是查询方式
TR1 = 1;
}
unsigned int count;
void main()
{
Serial_Init();
while(1)
{
for(count=0;count<8;count++)
{
Send(Tab[count]);
Delay();
}
}
}
单片机接收计算机发送的数据(重点)
#include <reg51.h>
void Serial_Init()
{
SCON = 0x50;//0101 0000
PCON = 0x00;
TMOD = 0x20;
TL1 = 0xFD;
TH0 = 0xFD; //波特率9600
EA = 1;
ES = 1; //EA和ES可以不写,因为这里用的是查询方式
TR1 = 1;
}
unsigned char Recevive()
{
unsigned char data;
while(RI == 0); //接收数据
RI = 0;
data = SBUF;
return data;
}
void main()
{
Serial_Init();
while(1)
{
P1 = Receive();
}
}
数码管的实现(重点)
#include <reg51.h>
unsigned char Nixie_Table[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void Delay(unsigned int i)
{
unsigned int j;
while(i--)
{
for(j=0;j<120;j++);
}
}
void Nixie(unsigned location,unsigned number)
{
switch(location)
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 9:P2_4=0;P2_3=0;P2_2=0;break;
}
P0 = Nixie_Table[number];
Delay(1);
P0 = 0x00; // 消影子
}
矩阵键盘的实现(重点)
#include <reg51.h>
void Delay(unsigned int i)
{
unsigned int j;
while(i--)
{
for(j=0;j<120;j++);
}
}
unsigned char MartrixKey()
{
unsigned char KeyNumber;
P1 = 0xFF;
P1_3 = 0;
if(P1_7 == 0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
if(P1_6 == 0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
if(P1_5 == 0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
if(P1_4 == 0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}
P1 = 0xFF;
P1_2 = 0;
if(P1_7 == 0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
if(P1_6 == 0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
if(P1_5 == 0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
if(P1_4 == 0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}
P1 = 0xFF;
P1_1 = 0;
if(P1_7 == 0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
if(P1_6 == 0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
if(P1_5 == 0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
if(P1_4 == 0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}
P1 = 0xFF;
P1_0 = 0;
if(P1_7 == 0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
if(P1_6 == 0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
if(P1_5 == 0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
if(P1_4 == 0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}
return KeyNumber;
}
DAC0832输出锯齿波
#include <reg51.h>
#include <absacc.h>
#define DAC0832 XBYTE[0x7FFF]
void stair()
{
unsigned char i;
for(i=0;i<255;i++)
{
DAC0832 = i;
}
}
DAC0832输出三角波
#include <reg51.h>
#include <absacc.h>
#define DAC0832 XBYTE[0x7FFF]
void triangle()
{
unsigned char i;
for(i=0;i<255;i++)
{
DAC0832 = i; //上升沿
}
for(i=255;i>0;i--)
{
DAC0832 = i; // 下降沿
}
}
DAC0832输出矩形波
#include <reg51.h>
#include <absacc.h>
#define DAC0832 XBYTE[0x7FFF]
void rectangular()
{
DAC0832 = 0xAF; //上限电平
Delay();
DAC0832 = 0x10; //下限电平
Delay()
}
ADC转换
#include <reg51.h>
#include <absacc.h>
#define ADCstart 0x7FFF
#define ADCdata 0x2000
unsigned char i;
void main()
{
i = 8; //8路模拟信号
EA = 1;
EX1 = 1;
IT1 = 1;
XBYTE[ADCstart] = i;
while(i);
}
void int1() interrupt 2
{
unsigned char temp;
temp = XBYTE[ADCstart];
i--;
XBYTE[ADCdata+i] = temp;
XBYTE[ADCstart] = i;
}