基于单片机的红外遥控小车
_nop_(); }while(--n); }
void ds18b20Init(void) { DQ = 0;
delay15us(54); //拉低约510us, 符合协议要求的480us以上 DQ = 1; //产生一个上升沿, 进入等待应答状态 delay15us(2); //拉高约30us }
void ds18b20Wait(void) //接受来自DS18B20的响应信号 {
while(DQ); //等待总线变低 while(~DQ); //检测到应答脉冲 delay15us(3);//延时45us }
//向DS18B20读取一位数据
//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平, //之后DS18B20则会输出持续一段时间的一位数据 bit readBit(void) { uint i; bit dat; DQ=0;
i++; //延时约8us, 符合协议要求至少保持1us DQ=1;
i++; i++; //延时约16us, 符合协议要求的至少延时15us以上 dat=DQ;
delay15us(5); //延时约75us, 符合读时隙不低于60us要求 return dat; }
uchar readByte(void) //读取一字节数据, 通过调用readBit()来实现 { uchar i, j,dat; for(i=1; i<=8; i++)
{j=readBit();//最先读出的是最低位数据 dat=(j<<7)|(dat>>1); }return dat; }
void writeByte(uchar dat) //向DS18B20写入一字节数据 {uint i; uchar j; bit b;
for(j=0;j<8;j++) { b=dat&0x01; dat>>=1;
if(b) //若此位为高,写1
第34页
基于单片机的红外遥控小车
{ DQ= 0;
i++; i++; //拉低约16us, 符号要求15~60us内 DQ=1;
delay15us(5); //延时约75us, 符合读时隙不低于60us要求 }
else //写\将DQ拉低60us~120us {
DQ=0;
delay15us(5); //延时约75us, 符合读时隙不低于60us要求 DQ=1; i++; i++; } } }
void sendChangeCmd(void)reentrant//向DS18B20发送温度转换命令 {ds18b20Init();//初始化DS18B20, 无论什么命令, 首先都要发起初始化 ds18b20Wait();//等待DS18B20应答 delay15us(67);
//延时约1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号 writeByte(0xcc); //写入跳过序列号命令字 Skip Rom writeByte(0x44); //写入温度转换命令字 Convert T }
void sendReadCmd(void) //向DS18B20发送读取数据命令 { ds18b20Init(); ds18b20Wait(); delay15us(67);
writeByte(0xcc); //写入跳过序列号命令字 Skip Rom writeByte(0xbe); //写入读取数据令字 Read Scratchpad }
void getTmpValue(void)reentrant//获取当前温度值 { uchar low, high; sendReadCmd();
low=readByte(); //读取温度值低位 high=readByte(); //读取温度值高位 temp_value=high<<4;
temp_value+=low>>4; }
void temp_to_str() reentrant //温度数据转换成液晶字符显示 { unsigned char i;
TempBuffer[0]=temp_value/10+'0'; //十位 TempBuffer[1]=temp_value+'0'; //个位 TempBuffer[2]=0xdf; //温度符号 TempBuffer[3]='C'; TempBuffer[4]='\\0'; }
第35页
基于单片机的红外遥控小车
void time1() interrupt 3 using 3 { TH1=(65536-4000)/256; TL1=(65536-4000)%6; sendChangeCmd(); getTmpValue();
temp_to_str(); }
void time1_init()
{ TMOD|=0x10;//定时器1为16位 TH1=(65536-4000)/256; TL1=(65536-4000)%6; ET1=1; TR1=1; }
*******************************************************************
4 TC9012.h
#include
sbit IR=P3^3;//红外接口标志
unsigned char irtime;//红外用全局变量 unsigned char count;
bit irpro_ok,irok; unsigned char IRcord[4]; unsigned char irdata[33]; unsigned char count_time=0;
void tim0_isr (void) interrupt 1 using 1//定时器0中断服务函数 { if(++count==20)
{irtime++;count=0;} LED=~LED; }
void ex1_isr (void) interrupt 2 using 2//外部中断1服务函数 {static unsigned char i; static bit startflag; if(startflag)
{ if(irtime<42&&irtime>=33)//引导码 TC9012的头码 i=0;
irdata[i]=irtime;//一次存储32位电平宽度 count=0;
第36页
基于单片机的红外遥控小车
irtime=0; i++; if(i==33) {
irok=1; i=0; } } else
{count=0;irtime=0;startflag=1;irok=0;} }
void time0_init(void)//定时器0初始化 {
TMOD|=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值 TH0=243; TL0=243;
ET0=1;//开中断 TR0=1; }
void EX1_init(void) {
IT0 = 1; EX0 = 1; }
void Ircordpro(void)//红外码值处理函数 {
unsigned char i, j, k; unsigned char cord,value; k=1;
for(i=0;i<4;i++)//处理4个字节 {
for(j=1;j<=8;j++) //处理1个字节8位 {
cord=irdata[k];
if(cord>7)//大于某值为1 {
value=value|0x80; } else {
value=value; }
if(j<8) {
第37页
基于单片机的红外遥控小车
value=value>>1; } k++; }
IRcord[i]=value; value=0;
} irpro_ok=1;//处理完毕标志位置1 }
*******************************************************************
5 speed.h
#include
#define MSB_reload_value (65536-1000)/256 #define LSB_reload_value (65536-1000)%6 unsigned char count0 = 0; unsigned char count1 = 0;
bit Flag=1;//电机正反转标志位,1正转,0反转 sbit PWM1=P0^0;//PWM 通道 1 sbit PWM2=P0^1;//PWM 通道 2 sbit PWM3=P0^2;//PWM 通道 3 sbit PWM4=P0^3;//PWM 通道 4
void Timer2(void) interrupt 5 //定时0中断处理 { TF2 = 0;
if(Flag==1)//电机正转 { PWM1=0; PWM3=0;
if(++count1 < count0) {PWM2=1;PWM4=1;} else { PWM2=0;PWM4=0;} }
else //电机反转 { PWM2=0; PWM4=0;
if(++count1 < count0) {PWM1=1;PWM3=1;} else {PWM1=0; PWM3=0;} }
if(count1 >= 100) count1=0; }
void time2_init(void)//定时器0初始化 {T2MOD=0X00;
EXF2=0; TCLK=0;
RCLK=0;
EXEN2=0;
第38页