一.利用中断发出1Khz的方波信号,驱动蜂鸣器鸣叫
1.利用T1的中断控制P1.7引脚输出频率为1kHz方波音频信号,驱动蜂鸣器发声。系统时钟为12MHz。方波音频信号周期1ms,因此T1的定时中断时间为0.5 ms,进入中断服务程序后,对P1.7求反。电路见图如下:
代码如下:
#include<reg51.h>
sbit sound=P2^5;
#define f1(a) (65536-a)/256
#define f2(a) (65536-a)%256
unsigned int i=500;
unsigned int j=0;
void t1 (void) interrupt 3 using 0
{
TR1=0;
sound=~sound;
TH1=f1(i);
TL1=f2(i);
j++;
TR1=1;
}
void main(void)
{
EA=1;
ET1=1;
TMOD=0X10;
TH1=f1(i);
TL1=f2(i);
TR1=1;
while(1)
{
i=460;
while(j<2000);
j=0;
i=360;
while(j<2000);
j=0;
}
}
结果如下:
二.LED数码管秒表的制作
1.用2位数码管显示计时时间,最小计时单位为“百毫秒”,计时范围0.1~9.9s。当第1次按一下计时功能键时,秒表开始计时并显示;第2次按一下计时功能键时,停止计时,将计时的时间值送到数码管显示;如果计时到9.9s,将重新开始从0计时;第3次按一下计时功能键,秒表清0。再次按一下计时功能键,则重复上述计时过程。
Proteus电路图如下:
代码如下:
#include<reg51.h>
typedef unsigned int uint; //定义无符号整形和字符型
typedef unsigned char uchar;
uchar led[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //共阳数码管 0 - 9
uchar led1[] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //共阳数码管 0 - 9 加小数点
uchar second; //秒数
uchar key; //按键次数
uint t; //用来计数,每500,代表0.1s
sbit keyif = P3^7; //按键接口
void delay(){ //延时函数,用于消除抖动
uchar i,j;
for(i=0;i<255;i++){
for(j=0;j<100;j++);
}
}
void init(void) //初始化
{
TMOD = 0x02; //0000 0010 使用方式二
second = 0; //秒数初始化为0
EA = 1; //总中断,定时器0中断允许
ET0 = 1; //允许定时器0中断
key = 0; //按键次数初始化为0
t = 0; //计数初始化为0
}
void main(){
init();
P0 = led1[second/10];
P2 = led[second%10];
while(1){
if(keyif == 0){
delay();//消除抖动
if(keyif == 0){
key++;
switch(key){
case 1: //按一次,计时器开始
TH0 = 0x38;
TL0 = 0x38; //200us,也就是0.2ms
TR0 = 1;
break;
case 2: //按两次,暂停定时器
t = 0;
TR0 = 0;
break;
case 3: //按三次,停止计时,数据清零
key = 0;
second = 0;
P0 = led1[0];
P2 = led[0];
break;
}
while(keyif == 0); //若一直按下,使其停留
}
}
}
}
void timer() interrupt 1
{
TR0 = 0; //停止计时
t++;
if(t == 500){
second++;
P0 = led1[second/10];
P2 = led[second%10];
t = 0;
}
if(second == 99){ //当计数到9.9秒,重新开始计时
second = 0;
key = 1; //相当于重新开始计时
}
TR0 = 1; //继续启动计时器
}
结果如下:
效果如下:
三.使用定时器实现一个LCD显示时钟
使用定时器实现一个LCD显示时钟。采用LCD 1602,具体见第5章的绍。LCD时钟的原理电路见图:
代码如下:
#include<reg51.h>
#include "LCD1602.h" //包含LCD1602头文件
#include "Delay.h" //包含Delay头文件
#define uchar unsigned char
#define uint unsigned int
uint int_time;
uint second;
uint minute;
uint hour;
void t0_interserve(void) interrupt 1 using 1
{
int_time++;
if(int_time==20)
{
int_time=0;
second++;
}
if(second==60)
{
second=0;
minute++;
}
if(minute==60)
{
minute=0;
hour++;
}
if(hour==24)
{
hour=0;
}
TH0=(65536-46083)/256;
TL0=(65536-46083)%256;
}
void show_time(h,m,s)
{
LCD_ShowNum(2,6,h,2);
LCD_ShowChar(2,8,':');
LCD_ShowNum(2,9,m,2);
LCD_ShowChar(2,11,':');
LCD_ShowNum(2,12,s,2);
}
void main()
{
LCD_Init();
LCD_ShowString(1,0,"H.I.T.CHINA");
LCD_ShowString(2,0,"TIME ");
TMOD=0X01;
EA=1;
ET0=1;
TH0=(65536-46483)/256;
TL0=(65536-46483)%256;
TR0=1;
int_time=0;
second=55;
minute=59;
hour=23;
while(1)
{
show_time(hour,minute,second);
}
}
电路图:
实验结果:
四.甲乙两个单片机串口通信
如图,甲、乙两单片机进行 方式3(或方式2)串行通信。甲机把控制8个流水灯点亮的数据发送给乙机并点亮其P1口的8个LED。方式3比方式1多了1个可编程位TB8,该位一般作奇偶校验位。乙机接收到的8位二进制数据有可能出错,需进行奇偶校验,其方法是将乙机的RB8和PSW的奇偶校验位P进行比较,如果相同,接收数据;否则拒绝接收。
发送机代码:
#include<reg51.h>
sbit p=PSW^0;//定义了一个特殊位变量(sbit)P,并将其映射到特殊功能寄存器PSW的第0位
unsigned char Tab[8]= {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,
0xbf,0x7f};
void Send(unsigned char dat)
{
TB8=p;
SBUF=dat;
while(TI==0);
;
TI=0;
}
void delay(void)
{
unsigned char m,n;
for(m=0;m<250;m++)
for(n=0;n<250;n++);
}
void main (void)
{
unsigned char i;
TMOD=0x20;
SCON=0xc0;
PCON=0x00;
TH1=0xfd;
TL1=0xfd;
TR1=1;
while(1)
{
for(i=0;i<8;i++)
{
Send(Tab[i]);
delay();
}
}
}
接受机代码:
#include<reg51.h>
sbit p=PSW^0;
unsigned char Receive(void)
{
unsigned char dat;
while(RI==0);
;
RI=0;
ACC=SBUF;
if(RB8==P)
{
dat=ACC;
return dat;
}
}
void main(void)
{
TMOD=0x20;
SCON=0xd0;
PCON=0x00;
TH1=0xfd;
TL1=0xfd;
TR1=1;
REN=1;
while(1)
{
P2=Receive();
}
}
效果如下:
五.hello 51
将单片机串口与笔记本电脑串口模块相连,单片机每隔2秒发送“Hello C51”,笔记本电脑用串口助手软件接收。 如果串口助手发送字符“0" 给单片机,则单片机停止发送; 如果单片机收到“1”,则继续每隔2秒发送“Hello C51”
代码如下:
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
uint p=0;//默认设置状态0
void delay_2s()//延时函数
{
int i,j;
for(i=0;i<21800;i++)
{
for(j=10;j>0;j--);
}
}
void uart_sendbyte(uchar byte)//发送字符
{
SBUF=byte;
while(TI==0);
TI=0;
}
void helloc51()
{
uart_sendbyte('h');
uart_sendbyte('e');
uart_sendbyte('l');
uart_sendbyte('l');
uart_sendbyte('o');
uart_sendbyte('c');
uart_sendbyte('5');
uart_sendbyte('1');
uart_sendbyte(' ');
}
void uart_init(uchar baud)//uart初始化
{
TMOD|=0X20;
SCON=0X50;
PCON=0X80;
TH1=baud;
TL1=baud;
ES=1;
EA=1;
TR1=1;
}
void uart() interrupt 4
{
if(RI==1)//读取串口发送的信息
{
uchar rec_data;
rec_data=SBUF;
RI=0;
if(rec_data==0)//发送0,设置为模式0
{
p=0;
}
else if(rec_data==1)发送1,设置为模式1
{
p=1;
}
}
}
void main()
{
uart_init(0XFA);
while(1)
{
if(p==0)//状态0,不做操作
{
while(p==0)
{
}
}
else if(p==1)//状态1,循环输出hello c51并且延时2s
{
while(p==1)
{
helloc51();
delay_2s();
}
}
}
}
结果: