📄 dpj.txt
字号:
#include "reg52.h"
#include "stdio.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
sfr T2MOD = 0xc9;
sbit DIN7219 = P2^0;
sbit CS7219 = P2^1;
sbit CLK7219 = P2^2;
sbit yhwfs = P0^0; //前方红外检测发送控制口
sbit qhwfs = P0^1; //左方红外检测发送控制口
sbit zhwfs = P0^2; //右方红外检测发送控制口
sbit CS1543 = P0^3; //TLC1543片选,低电平有效
sbit DT1543 = P0^4; //TLC1543数字量数据输出口
sbit AD1543 = P0^5; //TLC1543模拟通道地址输入口
sbit CK1543 = P0^6; //TLC1543工作时钟输入口
//TLC1543模拟通道0,1,2,3,4,5分别为红外检测的右方0,前方1,左方2,光敏电阻的右寻迹3,左寻迹4,中寻迹5
sbit HWK = P0^7; //红外遥控接收口
sbit D18b20 = P1^0; //18B20数据口
sbit FMQ = P2^7; //蜂鸣器控制口 低电平蜂鸣器响
sbit LED1 = P2^3; //低电平点亮
sbit LED2 = P2^4;
sbit LED3 = P2^5;
sbit LED4 = P2^6;
sbit ztsk = P3^0; //左电机调速输出口
sbit ytsk = P3^1; //右电机调速输出口
sbit zjsk = P3^2; //左电机测速脉冲输入口,INT0中断,边缘触发
sbit yjsk = P3^3; //右电机测速脉冲输入口,INT1中断,边缘触发
sbit zin = P3^4; //左电机正反转控制口
sbit yin = P3^5; //右电机正反转控制口
sbit zen = P3^6; //左电机供电允许控制口
sbit yen = P3^7; //右电机供电允许控制口
//sbit = P1^5;
//sbit = P1^6;
//系统剩余端口:P10到P14及P27共6个
bit hwkjz; //红外口禁止
bit sxjz; //刷新显示禁止
bit zxrwt,kk,zxrwtt; //执行任务状态,工作用位变量,即将完成执行任务状态
bit lszt=0;
bit lll=0;
bit dwdjz=0; //读温度禁止
bit fmqzt=0; //蜂鸣器状态
bit wtjct=0; //前进物体检验状态
bit zanting; //小车暂停/取消暂停
//bit onoff;
uchar idata xcq[9]={0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f}; //显示存储区
uint idata adsj[11]; //A/D转换数据存储区,二进制数
uchar idata adsjc[11]; //A/D转换数据存储区,已转为十进制数
uchar idata wendu[2]; //读18b20的温度数据,高字节ssssszzz 低字节zzzz.xxxx
uchar idata wenduc[5]; //经处理后的温度数据,[4]为符号,[3][2][1]为整数字,[0]为小数
uchar code wdxs[16]={0x00,0x01,0x01,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
//温度小数部分用查表法
float wenduf;
uchar xsfs,jz,hwkjzys; //显示方式,键值,红外口禁止延时
uchar sxjzys; //刷新显示禁止延时
uchar tsjs,ztsds,ytsds; //调速计数,左电机档数,右电机档数
uchar hh,ss,mm; //计时秒,分
uchar sss,mmm; //执行任务计时秒,分
uchar gzhh,gzmm; //定时启动小车工作的时间,小时,分钟
uchar zxjs90; //转向90度脉冲数
uchar ccc,ll; //临时
uchar fmqxys; //蜂鸣器发声延时
uchar xczt; //小车状态字,0,1,2,3,4,5,分别为停车0,前进1,倒退2,左转3,右转4,转向完成临时停车5,6
//任务时:任务1寻线前进11,任务2寻线后退12,任务3垂直前进13,任务4垂直后退14,
//检测块:tq2时为21,tq5时为22,
uchar zjs,yjs; //转向时左右轮临时脉冲计数
uchar z0,zh0,y0; //左中右寻迹比较阈值电平
//实测各路最小(黑带内)/最大(白底)为z:3.3V/4.5V,y:2.3V~4.2V,zh:2.1V~4.5V
uchar qy0,qz0; //前左右寻迹比较阈值电平
uchar tq20,tq50; //气敏元件电压阈值
uchar qfwt;
uchar s,lm,l; //水平横线长度(脉冲数),横线条数,小车当前寻迹线数
uchar xjqk,xjqk0,xjqkq,xjqkn,jpt; //寻迹情况,寻迹情况上次值,前方寻迹情况,寻迹情况连续相同值次数,纠偏状态
uint zjsn,yjsn; //左右轮前进累计脉冲计数
uint n1000; //T2定时中断1000次计数(1秒)
uint n500; //T2定时中断500次计数(半秒)-蜂鸣器使用
//uint t0n,t0n0,nn;
void xtcsh(void); //系统初始化
void init_Max7219(void);
void Write_Max7219(uchar address,uchar dat); //
void Write_Max7219_byte(uchar kk);
uchar dhwk(void); //读红外遥控口
uchar dhwsj(void); //读红外遥控键值
void zxml(uchar jz); //
void sxxs(uchar fs); //刷新显示_LED数码管显示
void delay(uchar l); //
void delay2(uint l);
uint adzh(uchar adtd); //A/D转换_TLC1543
void zxrw(void); //执行任务
uchar xjqkfx(void); //寻迹情况分析
uchar ezhs(uint sj); //二进制转换十进制
void tq2(void); //TQ-2气体传感器
void tq5(void); //TQ-5气体传感器
void wdcg(void); //温度传感器
void dwd(void); //读18b20温度
void fw18b20(void); //复位18b20
void write18b20_byte(uchar val); //写18b20一字节
uchar read18b20_byte(void); //读18b20一字节
void wdsjcl(void); //温度数据处理
/*************************************************/
void xtcsh(void) //系统初始化
{
zen=0;yen=0;
zin=1;yin=1;
xczt=0;
zhwfs=qhwfs=yhwfs=0;
ztsds=40;ytsds=40;tsjs=0;
LED1=1;LED2=1;LED3=1;LED4=1;
TMOD=0x11;
T2CON=0x00;
TH2=0xfc; //定时1ms
TL2=0x67;
RCAP2H = 0xfc; //自动重装初值寄存器
RCAP2L = 0x67;
TR2=1;
ET2=1;
TF2=0;
IT0=1;EX0=1; //允许int0外部中断,边沿触发
IT1=1;EX1=1; //允许int1外部中断,边沿触发
EA=1;
xsfs=0;
hwkjz=0;
// xwz=0x01;
hwkjz=0;
sxjz=0;
sxjzys=200;
ss=10;mm=59;hh=23;
sss=mmm=0;
zxjs90=16;
s=50;lm=6; //水平横线长度(脉冲数),横线条数
z0=zh0=y0=38;//实测各路最小(黑带内)/最大(白底)为z:3.3V/4.5V,y:2.3V~4.2V,zh:2.1V~4.5V,此均取3.8V为判断阈值
qy0=qz0=35; //前寻线阈值
tq20=10; //TQ-2气体传感器的阈值
tq50=10; //TQ-5气体传感器的阈值
fmqzt=0; //蜂鸣器状态,静声
zxrwt=0;
qfwt=20; //红外检测前方物体阈值电平
FMQ=0;
fw18b20();
write18b20_byte(0xcc);
write18b20_byte(0x44);
delay(10);
ccc=0xff;
zanting=0; //预置小车非暂停状态
gzhh=23;gzmm=0; //预置小车定时自动启动工作的时间
}
/*************************************************/
void Write_Max7219_byte(uchar kk)
{
uchar i;
CLK7219=0;
for(i=0;i<8;i++)
{
DIN7219=(bit)(kk & 0x80);
kk<<=1;
CLK7219=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
CLK7219=0;
}
}
/*************************************************/
void Write_Max7219(uchar address,uchar dat)
{
DIN7219=0;
CLK7219=0;
CS7219=0;
Write_Max7219_byte(address);
Write_Max7219_byte(dat);
CS7219=1;
}
/*************************************************/
void init_Max7219(void)
{
Write_Max7219(0x0c,0x01); //关断模式寄存器(0ch),开启正常工作模式(0xX1)
Write_Max7219(0x09,0xff); //译码控制寄存器(09h),选用全译码模式(0xff)
Write_Max7219(0x0b,0x07); //扫描界限寄存器(0bh),8位全用
Write_Max7219(0x0a,0x06); //亮度控制寄存器(0ah),最大亮度0fh,设置初始亮度06h
Write_Max7219(0x0f,0x00); //测试控制寄存器(0fh),选择工作模式(0xX0)
}
/*
;测试寄存器地址为0FH,数据01H为测试,00H为正常工作
;7219的8个数码管的地址为01H(最低位)到08H(最高位)
;发送子程序,数据由R3(地址)和R4(数据)带来,共发16位
;B译码为BCD码,0AH~0EH为-,E,H,L,P,OFH为消隐,小数点为8XH
*/
/*************************************************/
void delay(uchar l) //延时125*11=1375微秒
{ uchar i;
while(l--)
{
for(i=0;i<125;i++)
{ ; }
}
}
/*************************************************/
void delay2(uint l) //延时11微秒
{
for(;l>0;l--)
{ ; }
}
/*************************************************/
uint adzh(uchar adtd)
{
uchar i,j,ah,al;
uint ad;
j=adtd;ah=0;al=0;
if(j==0) yhwfs=1;
if(j==1) qhwfs=1;
if(j==2) zhwfs=1;
CS1543=0; //选中1543芯片
_nop_();
for(i=1;i<5;i++) //先发A/D通道地址(4bit) //添加
{
AD1543=(bit)(j&0x08); //从高位发起,送1543数据线
CK1543=1; //发正脉冲到1543时钟线
CK1543=0;
j<<=1; //发下一位
}
for(i=1;i<7;i++) //再发6位空地址为
{
CK1543=1;
CK1543=0;
}
CS1543=1; //拉起1543CS电平,1543开始A/D转换
for(i=0;i<15;i++) //等待转换完成
{ _nop_();}
CS1543=0; //再选中1543,准备读取转换数据
for(i=1;i<3;i++) //先读高2位(共10位)存在高字节
{
CK1543=1;DT1543=1; //拉起时钟线,数据线电平
ah<<=1; //准备接收下一位(预先填0)
if(DT1543) ah|=0x01; //如果数据线为高电平则改为1
CK1543=0; //降下时钟线电平,完成1bit的读取
}
for(i=1;i<9;i++) //再读取数据的低8位,存在低字节
{
CK1543=1;DT1543=1;
al<<=1;
if(DT1543) al|=0x01;
CK1543=0;
}
CS1543=1; //完成数据读取,结束对1543的访问
ad=(uint)(ah);ad<<=8;ad|=al; //将高低字节组合
ad*=5; //乘基准电压5V,低10位应为小数部分
zhwfs=0;qhwfs=0;yhwfs=0;
return(ad);
}
/*************************************************/
void sxxs(uchar fs) //刷新显示
{ uchar i,j,b,c;
// float x;
switch(fs)
{
case 0: { //fs=0时显示时间
xcq[0]=ss%10;xcq[1]=ss/10;
xcq[2]=(mm%10)|0x80; //分钟个位数和小数点
xcq[3]=mm/10;
xcq[4]=(hh%10)|0x80; //小时个位数和小数点
xcq[5]=hh/10;
xcq[6]=xcq[7]=0x0f;
break;
}
case 1: { //fs=1时显示路程,前进的累计计数
xcq[0]=yjsn%10; //左轮脉冲数写入显存区
xcq[1]=(yjsn%100)/10;
xcq[2]=(yjsn%1000)/100;
xcq[3]=yjsn/1000;
xcq[4]=(zjsn%10)|0x80; //左轮脉冲数写入显存区
xcq[5]=(zjsn%100)/10;
xcq[6]=(zjsn%1000)/100;
xcq[7]=zjsn/1000;
break;
}
case 2: { //fs=2时显示左右电机设置的调速档数
xcq[0]=ytsds%10; //右轮档数写入显存区
xcq[1]=(ytsds%100)/10;
xcq[2]=(ytsds%1000)/100;
xcq[3]=ytsds/1000;
xcq[4]=(ztsds%10)|0x80; //左轮档数写入显存区
xcq[5]=(ztsds%100)/10;
xcq[6]=(ztsds%1000)/100;
xcq[7]=ztsds/1000;
break;
}
case 3: { //显示左前右三路红外检测A/D转换的电压值,显示z.z q.q y.y
if(sxjz==0)
{ for(i=0;i<3;i++) //分别为TL1543的模拟通道0,1,2
{ j=i*3;
c=adsjc[i]/10; //取整数部分
b=adsjc[i]%10; //取十分位数字
xcq[j]=b;xcq[j+1]=c|0x80;xcq[j+2]=0x0f; //分别送显存区待显 X.X
}
sxjz=1;
}
break;
}
case 7: { //显示底盘左右红外检测A/D转换的电压值,显示z.z q.q y.y
if(sxjz==0)
{ for(i=7;i<9;i++) //分别为TL1543的模拟通道1,2
{ j=(i-7)*3;
c=adsjc[i]/10; //取整数部分
b=adsjc[i]%10; //取十分位数字
xcq[j]=b;xcq[j+1]=c|0x80;xcq[j+2]=0x0f; //分别送显存区待显 X.X
}
sxjz=1;
xcq[6]=xcq[7]=0x0f;
}
break;
}
case 8: { //显示18b20所测温度值,szzz.x
xcq[0]=wenduc[0]; //十分位
xcq[1]=wenduc[1]|0x80; //个位,后加小数点
xcq[2]=wenduc[2]; //十位
xcq[3]=wenduc[3]; //百位
if(xcq[3]==0)
{ xcq[3]=0x0f;
if(xcq[2]==0) xcq[2]=0x0f;
}
xcq[4]=0x0f; //符号位
if(wenduc[4]==1) xcq[4]=0x0a; //为负号
xcq[5]=xcq[6]=xcq[7]=0x0f;
break;
}
case 9: { //显示执行任务时间,mm.ss
xcq[0]=sss%10;xcq[1]=sss/10;
xcq[2]=(mmm%10)|0x80; //分钟个位数和小数点
xcq[3]=mmm/10;
xcq[4]=xcq[5]=xcq[6]=xcq[7]=0x0f;
break;
}
case 4: { //显示底盘左中右三路光敏电阻寻迹检测A/D转换的电压值
if(sxjz==0)
{ for(i=3;i<6;i++) //分别为TL1543的模拟通道中5,左4,右3
{ j=(i-3)*3;
c=adsjc[i]/10; //取整数部分
b=adsjc[i]%10; //取十分位数字
xcq[j]=b;xcq[j+1]=c|0x80;xcq[j+2]=0x0f; //分别送显存区待显 X.X
}
sxjz=1;
}
break;
}
case 5: { //fs=5时显示左右转向时的临时计数
xcq[0]=yjs%10; //右轮脉冲数写入显存区
xcq[1]=(yjs%100)/10;
xcq[2]=(yjs%1000)/100;
xcq[3]=0x0f;
xcq[4]=(zjs%10)|0x80; //左轮脉冲数写入显存区
xcq[5]=(zjs%100)/10;
xcq[6]=(zjs%1000)/100;
xcq[7]=0x0f;
break;
}
case 6: { //fs=6时显示qkfx实时值
b=ccc/10;
xcq[0]=ccc%10;
xcq[1]=b%10;
xcq[2]=ccc/100;
xcq[3]=0x0f;
xcq[4]=0x0f;
xcq[5]=0x0f;
xcq[6]=xjqkq;
xcq[7]=0x0f;
break;
}
default:{ break; }
}
for(j=0;j<8;j++) { Write_Max7219(j+1,xcq[j]); } //将显存数据送7219显示
}
/*************************************************/
void zxrw(void) // 执行任务
{ uchar zh,qy,qz;
xjqk=xjqkfx();
zh=adsjc[5]; //中寻线标志
qy=adsjc[0]; //前右寻线标志
qz=adsjc[2]; //前左寻线标志
switch(xczt)
{
case 11:{ //寻线前进
if((zjsn>s)|(yjsn>s)) //走到线左端,应后退返回
{ zen=0;yen=0;zin=0;yin=0;
zjsn=yjsn=s;
delay(100);
zen=yen=1;xczt=12;
}
else
{
if((xjqkq==0x02)&(jpt!=1)) //左偏
{ ztsds=49;ytsds=5;
// if(ztsds>49) ztsds=49;
jpt=1; //纠左偏状态
}
if((xjqkq==0x01)&(jpt!=2)) //右偏
{ ztsds=5;ytsds=49;
// if(ytsds>49) ytsds=49;
jpt=2; //纠右偏状态
}
/* if((qy<qy0)&(jpt!=10)) //左微偏
{ ztsds+=5;ytsds-=5;
jpt=10; //纠左微偏状态
}
if(((xjqk==4)|(xjqk==6))&(jpt!=1)) //左偏
{ ztsds+=9;ytsds-=9;
if(zh>40) {ztsds+=5;ytsds-=5;} //左偏严重
if(ztsds>49) ztsds=49;
jpt=1; //纠左偏状态
}
if((qz<qz0)&(jpt!=20)) //右微偏
{ ztsds-=5;ytsds+=5;
jpt=20; //纠右微偏状态
}
if(((xjqk==1)|(xjqk==3))&(jpt!=2)) //右偏
{ ztsds-=9;ytsds+=9;
if(zh>40) {ztsds-=5;ytsds+=5;} //右偏严重
if(ytsds>49) ytsds=49;
jpt=2; //纠右偏状态
}
*/
if(xjqkq==0x03) {jpt=0;ztsds=ytsds=40;} //不偏
}
if((adsjc[1]>qfwt)&(!fmqzt)&(!wtjct))
{
FMQ=1;fmqzt=1;fmqxys=2; //启动蜂鸣器发声2次
wtjct=1; //前进物体检测状态
}
break;
}
case 12:{ //寻线后退
if((zjsn==0)|(yjsn=0)) //已退到线左端,本线寻完,应左转向后垂直运行
{ //
zen=0;yen=0;zin=0;yin=1; //准备左转
zjsn=yjsn=0;
delay(100);
zjs=yjs=0;ztsds=ytsds=40;zen=yen=1;xczt=3; //左转
}
else
/* {
if((xjqkq==0x02)&(jpt!=1)) //尾巴右偏
{ ytsds+=9;ztsds=10;
if(ytsds>49) ytsds=49;
jpt=1; //纠右偏状态
}
if((xjqkq==0x01)&(jpt!=2)) //尾巴左偏
{ ytsds=10;ztsds+=9;
if(ztsds>49) ztsds=49;
jpt=2; //纠左偏状态
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -