单片机定时器与串口通信
一、中断驱动蜂鸣器
频率计算方法:
频率 = 周期的倒数,即 f = 1/T,也可以说二者互为倒数 。
频率 f 的单位是赫兹Hz,周期T的单位是秒s。
一般我们通过频率来求得周期,比如1KHz的频率对应的周期就是1s/1000Hz=0.001s=1ms
我们通过延时函数在一个周期内输出相同时间的高电平和低电平模拟方波信号,将信号输送给 无源蜂鸣器驱动蜂鸣器发出声音。
代码实现:
#include <REGX52.H>
sbit sound=P3^5;
void main()
{
EA=1;
ET1=1;
TMOD=0x10;
TH1=0xfe;//中断500微秒
TL1=0x33;
TR1=1;
while(1)
{ }
}
void Timer1_Routine() interrupt 3 // 中断函数
{
TH1=0xfe;
TL1=0x33;
sound=~sound;
}
电路原理图:
二、LED数码管秒表的制作
将数码管的8个段当成8个LED小灯来控制,即a、b、c、d. e、f、g、dp- -共8个LED小灯。如果点亮b和c这两个LED小灯,也就是数码管的b段和c段,其他的所有的段都熄灭的话,就可以让数码管显示出一个数字1,以共阳极数码管为例,二进制数字为0b11111001,十六进制为0xF9。同理可得其他数字多对应的数码管的真值
代码实现:
#include<reg51.h>
typedef unsigned int uint; //定义无符号整形和字符型
typedef unsigned char uchar;
uchar led[] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar led1[] = {0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};
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 = 0x01; //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 = 0xee;
TL0 = 0x00;
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 ==20){
second++;
P0 = led1[second/10];
P2 = led[second%10];
t = 0;
}
if(second == 99){ //当计数到9.9秒,重新开始计时
second = 0;
key = 2; //相当于重新开始计时
}
TR0 = 1; //继续启动计时器
}
电路原理图:
三、LCD1602显示时钟
LCD1602液晶显示屏是一种字符型液晶显示模块,可以显示数字、字母、图形以及少量自定义字符。可以显示2行16个字符,拥有16个引脚,其中8位数据总线D0-D7,和RS、RW、EN三个控制端口。
代码实现:
#include"reg51.h"
sbit RS=P3^0;
sbit RW=P3^1;
sbit E=P3^2;
unsigned char s[]={“0123456789”};
unsigned char s1[]={“clock:”};
unsigned char num=0,sec=0,min=25,hour=12;
unsigned char temp0=0,temp1=0,temp2=0,temp3=0,temp4=0,temp5=0;
void delay(unsigned int m)
{
unsigned int i=0,j=0;
for(i=0;i<m;i++)
{
for(j=0;j<120;j++);
}
}
void writecom(unsigned char com)
{
RS=0;
RW=0;
E=0 ;
P2=com;
delay(5);
E=1;
E=0;
}
void writedat(unsigned char dat)
{
RS=1;
RW=0;
E=0 ;
P2=dat;
delay(5);
E=1;
E=0;
}
void initlcd()
{
writecom(0x38);
writecom(0x0c);
writecom(0x06);
writecom(0x01);
}
void inittime()
{
TMOD=0x01;//定时器0
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
void display()
{
unsigned int i=0;
temp0=sec%10;
temp1=sec/10;
temp2=min%10;
temp3=min/10;
temp4=hour%10;
temp5=hour/10;
writecom(0x80+0x46);
delay(5);
writedat(s[temp5]);
delay(5);
writedat(s[temp4]);
delay(5);
writedat(':');
delay(5);
writedat(s[temp3]);
delay(5);
writedat(s[temp2]);
delay(5);
writedat(':');
delay(5);
writedat(s[temp1]);
delay(5);
writedat(s[temp0]);
delay(5);
writecom(0x80);
delay(5);
while(s1[i]!='\0')
{
writedat(s1[i]);
i++;
}
}
void main()
{
initlcd();
inittime();
while(1)
{
display();
}
}
void inittime_isr() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
num++;
if(num20)
{
sec++;
num=0;
}
if(sec60)
{
min++;
sec=0;
}
if(min60)
{
hour++;
min=0;
}
if(hour24)
{
hour=0;
}
}
电路原理图:
四、甲乙两个单片机串口通信
异步串行通信是指收、发双方使用各自的时钟控制数据的发送和接收,这样可省去连接收、发双方的一条同步时钟信号线,使得异步串行通信连接更加简单且容易实现。为使收发双方协调,要求收、发双方的时钟尽可能一致。 异步串行通信不要求收、发双方时钟严格一致,实现容易,成本低,但是每个数据帧要附加起始位、停止位有时还要再加上校验位。同步串行通信相比异步串行通信,同步串行通信数据传输的效率较高,但是额外增加了一条同步时钟线。
甲、乙两单片机进行 方式3(或方式2)串行通信。甲机把控制8个流水灯点亮的数据发送给乙机并点亮其P1口的8个LED。方式3比方式1多了1个可编程位TB8,该位一般作奇偶校验位。乙机接收到的8位二进制数据有可能出错,需进行奇偶校验,其方法是将乙机的RB8和PSW的奇偶校验位P进行比较,如果相同,接收数据;否则拒绝接收。