今天搞了第二个小项目吧,算是对我单片机学习上面一个质的飞跃,其实也就是舵机跟超声波传感器融合起来,随后再加上蜂窝以及震动传感器来加强用户需求,还是有很多细节要注意的,特别是中断那一块 ,外部中断和定时器中断,又是两个区别,一开始我就想着外部中断怎么跟传感器连接起来,后面我看到手册才发现,外部中断P3.2 是固定的 传感器插进那个串口就行了,还有定时器中断的话就是,在调用定时器定义的时候就已经开始计时,TL0 = 0x33;
TH0 = 0xFE; 我们已知65536是71ms,然后TL0 TH0就是相当于给一个初值 ,使得到达65536的时候刚好是10ms,所以就得出TL0 TH0 的数字。其他的话就是函数封装吧,把main函数里面的内容弄得尽量简洁 美观。
代码如下
#include "reg52.h"
sbit D5 = P3^7;
sbit D6 = P3^6;
sbit SW1 = P2^1;
sbit vibrate = P3^2;
sbit Trig = P1^5;
sbit Echo = P1^6;
sbit Bee = P2^0;
int cnt=0;
sbit sg90_con = P1^1;
int jd;
char mark_vibrate =0;
void Delay10us() //@11.0592MHz
{
unsigned char i;
i = 2;
while (--i);
}
void Delay150ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 2;
j = 13;
k = 237;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Time0init(){
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01;//定义一个定时器0
//2.给初值,定一个0.5ms出来
TL0 = 0x33;
TH0 = 0xFE;
//3.开始计时
TR0=1 ;
TF0=0;//默认先不爆表
//4.爆表了,累积到1s,再操作led}
ET0=1;//打开定时器0中断
EA = 1;//打开总中断EA
}
void Delay2000ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void funtion(){ //定义一个Trig的状态
Trig = 0;
Trig = 1;
Delay10us();
Trig = 0;
}
void Time1init(){
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10;
TH1 =0;
TL1 =0;
//设置定时器0工作模式1,初值为0开始数数。不着急启动定时器。
}
double Getdistance(){
//1,给Trig至少一个10us的脉冲
double time ;
funtion();
TH1 =0;//定时器清零,以便下次定时
TL1 =0;
//2,由低电平跳转到高电平,表示开始发送波,波发出去的那一下,开始启动定时器
while(Echo == 0);//表示循环完了进入高电平
TR1 = 1;//进入高电平的一瞬间 定时器开始定时
//3,由高电平跳转到低电平,表示波回来了
while (Echo ==1);
TR1 = 0;
//5,波回来的那一下,停止定时器,计算出中间经过的时间
time = (TH1 *256 +TL1)*1.085;//us为单位
//6,距离dis = 速度(340m/s)*时间/2
return (time * 0.017);
}
void openlight(){
D5 = 0;
D6 = 1;
}
void closelight(){
D5 = 1;
D6 = 0;
}
void sg90ini(){
jd = 1;//初始角度为0,0.5ms,溢出1就是0.5,高电平
cnt=0;
sg90_con = 1;//一开始从高电平开始
}
void opengai(){
int n;
jd=3;//90度,2ms高电平
cnt=0;
Bee =0;
for(n=0;n<4;n++)
Delay150ms();
Bee =1;
Delay2000ms();
}
void closegai(){
jd = 1;//初始角度为0,0.5ms,溢出1就是0.5,高电平
cnt=0;
Delay150ms();
}
void EX0_init(){
//添加外部中断
EX0 =1;
//低电平触发
IT0 =0;
}
void main()
{
double dis;
Time0init();
Time1init();
sg90ini();
EX0_init();
while(1){
//超声波测距
dis = Getdistance();
//调用外部中断函数
if(dis <10 || SW1 ==0|| mark_vibrate ==1 ){
//灯的状态
openlight();
opengai();
mark_vibrate =0;//恢复到0的状态
}
else {
closelight();
closegai();
}
}
}
void Time0Handler() interrupt 1//因为TMOD = 0x01 所以是定时器0 定时器0的中断 查询的序列是1
{
cnt ++;
//重新给初值
TL0=0x33;
TH0=0xFE;
if(cnt <jd){//控制pwm波
sg90_con=1;
}
else {
sg90_con =0;
}
if(cnt == 40){
cnt =0;
sg90_con=1;
}
}
void EX0_Handler() interrupt 0//外部中断函数
{
mark_vibrate = 1;
}