测试

【测试】宝剑锋从磨砺出,梅花香自苦寒来。这篇文章主要讲述测试相关的知识,希望能为你提供帮助。

#include< stc8a8k.h> #include< oled.h> #include< delay.h> #include< stdio.h> #include "hpwm.h" //***************************************************************************下面是接线定义 //左电机 sbit LPWM=P2^0; //电机调节速度的信号 sbit LA2=P0^4; sbit LA1=P0^5; //右电机 sbit RPWM=P2^1; sbit RA2=P0^6; sbit RA1=P0^7; //接传感器 sbit L1S=P1^0; sbit L0S=P1^1; sbit MS=P1^2; sbit R0S=P1^3; sbit R1S=P1^4; //************************************* sbit key=P3^4; //接按键,启动按键 sbit key1=P3^5; //接按键,停止按键,停止之后,显示运行时间和运行距离,不能实时显示 sbit beep=P0^3; //接蜂鸣器 sbit led=P0^0; //接LED报警灯 sbit metal=P3^2; //金属传感器,接P32引脚,中断触发,之后停止,报警,之后继续循迹 //****************************************************************************下面是全局变量的定义,每个函数都能使用 //定义黑白线的信号,根据实际模块定义,1是高电平,0是低电平,后面如果换模块, //不同模块的情况不一样,有些是碰到黑线是1,有些是0,就很容易修改 bit blackline=1; bit whiteline=0; bit displayflag=0; //这宏定义,后面如果小车需要调节速度,比较方便修改,直接改这里就好了。 #define vleftmove 0.35f #define vrightmove 0.35f//直线行走的速度#define vturnbig 0.45f #define vturnsmall 0.22f//转弯的速度差速度,一个是大,一个小,小转弯差速度#define vturnbigM 0.65f #define vturnsmallM 0.12f//转弯的速度差速度,大转弯差速度//************************************定义变量 unsigned int maichongnum=0; //脉冲个数 //float zhouchang=2.04; //小车直径65mm,3.14*65=204.2mm=2.04cm float distance=0.01f; unsigned int miao=0; //,fen=0,unsigned char disbuf[9]=0; //给显示浮点数使用 bit overtime2flag=0; //蓝牙接收到字符,左,右,前进,后退,停止,调头,开始循迹 #define cmdleft\'L\' #define cmdright\'R\' #define cmdup\'G\' #define cmddown\'D\' #define cmdstop\'S\' #define cmdback\'B\' #define cmdTrack\'T\' bitcmdflag_REC=0; bitcmdflag=0; unsigned charcmdnum=0; unsigned charcmddat=0; unsigned charcmdbuff[5]=0; //接收缓冲字节 //**************************************************************************************************下面是子函数的定义、或者声明 //循迹函数声明,先声明后定义,不然main都不知道有这个函数,在main函数后面定义具体程序代码 //****************************************************************子函数0:函数声明;void trackline0(); void trackline0(); //按键控制的循迹,到终点后,停止,然后调头,再循迹回到起点,不需要走过断线区域 voidtrackline1(); //蓝牙控制的循迹,到终点后,停止,用蓝牙走过挖空的断线区域,然后到到起点,再循迹 //****************************************************************子函数1:qianjin(float vleft,float vright) //这个是定义,不声明,后面main函数可以直接用, //小车前进,根据速度两个轮子速度差,进行前进,转弯等 void qianjin(float vleft,float vright) { HPWM_Set(0,8000,vleft); LA2=1; LA1=0; HPWM_Set(1,8000,vright); RA2=1; RA1=0; } //****************************************************************子函数2:void turnback(float vleft,float vright) //小车调头程序,左轮反转,右轮正转 void turnback(float vleft,float vright) { HPWM_Set(0,8000,vleft); LA2=0; LA1=1; HPWM_Set(1,8000,vright); RA2=1; RA1=0; } //****************************************************************子函数2:void turnback(float vleft,float vright) //小车后退程序,两个反转 void back(float vleft,float vright) { HPWM_Set(0,8000,vleft); LA2=0; LA1=1; HPWM_Set(1,8000,vright); RA2=0; RA1=1; } //****************************************************************子函数3:void stop() //小车停止 void stop() { LA2=0; LA1=0; RA2=0; RA1=0; } //*****************************************************************************************************下面是主函数 //*******************************************主函数 void main() { bit startflag=0; //按键控制的启动标记 bit startflag2=0; //蓝牙控制的启动标记 //每个外设,比如按键,屏幕,PWM等内部资源的初始化,配置一下环境 //设置准双向口,和普通的51单片机一样 P0M1=0x00; P0M0=0x00; P1M1=0x00; P1M0=0x00; P2M1=0x00; P2M0=0x00; P3M1=0x00; P3M0=0x00; P4M1=0x00; P4M0=0x00; P5M1=0x00; P5M0=0x00; P6M1=0x00; P6M0=0x00; delay_tms(200); //屏幕初始化 OLED_Init(); //PWM模块初始化 HPWM_Init(); //显示开机界面 OLED_ShowString(0,0,"Start,Please..."); //外部中断0初始化,接的是金属传感器 IT0 = 1; //使能INT0下降沿中断 EX0 = 1; //使能INT0中断 //外部按键中断接口INT2,P36,下降沿,按下P36,显示时间和距离数值 INTCLKO = EX2; //使能INT2中断 //定时器0初始化,计算启动的之后运行的时间//50毫秒@11.0592MHz AUXR & = 0x7F; //定时器时钟12T模式 TMOD & = 0xF0; //设置定时器模式 TL0 = 0x00; //设置定时初值 TH0 = 0x4C; //设置定时初值 TF0 = 0; //清除TF0标志 ET0=1; //打开定时器0的中断,允许定时时间到,进入到定时器程序 //定时器1初始化,作为蓝牙串口的波特率发生器,利用串口1,//9600bps@11.0592MHz SCON = 0x50; //8位数据,可变波特率 AUXR & = 0xBF; //定时器1时钟为Fosc/12,即12T AUXR & = 0xFE; //串口1选择定时器1为波特率发生器 TMOD & = 0x0F; //设定定时器1为16位自动重装方式 TL1 = 0xE8; //设定定时初值 TH1 = 0xFF; //设定定时初值 ET1 = 0; //禁止定时器1中断 TR1 = 1; //启动定时器1 //定时器T250毫秒@11.0592MHz,用来做超时检测,如果某个程序超过这个时间,就退出死循环。 AUXR & = 0xFB; //定时器时钟12T模式 T2L = 0x00; //设置定时初值 T2H = 0x4C; //设置定时初值 IE2 = ET2; //使能定时器中断 EA=1; //打开总的全局中断 //***************************************************************** //*********************************************正式执行程序 while(1) {//**************************************************************************按键来控制的 //***************************** //检测按键是不是按下,开始启动 if(key==0) { delay_tms(10); //延时去抖动 if(key==0) { startflag=1; OLED_ShowString(0,0,"running,GO,GO..."); stop(); delay_tms(1000); //延时,按下两秒之后,小车开始启动进行循迹 // delay_tms(2000); OLED_Clear(); IT1 = 1; //使能INT1下降沿中断,P33引脚是INT1 EX1 = 1; TR0 = 1; //定时器0开始计时} } //************************************************************************蓝牙控制的代码,前进,后退,左转,右转,停止,调头 if(cmdflag_REC==1)// { cmdflag_REC=0; if(cmdbuff[0]==\'O\'& & cmdbuff[1]==\'N\') //第一个字节为O,第二个字节为N,第三个字节为控制码,手机端发送的应该是0NB等 switch(cmdbuff[2]) { case cmdup :// 前进 startflag2=0; qianjin(vleftmove,vleftmove); break; case cmddown:// 后退 back(vleftmove,vrightmove); break; case cmdleft:// 左转 startflag2=0; qianjin(vturnsmall,vturnbig); break; case cmdright:// 右转 startflag2=0; qianjin(vturnbig,vturnsmall); break; case cmdstop:// 停止 stop(); break; case cmdback:// 调头 startflag2=0; turnback(vleftmove,vrightmove); break; case cmdTrack: startflag2=1; IT1 = 1; //使能INT1下降沿中断,P33引脚是INT1 EX1 = 1; TR0 = 1; //定时器0开始计时 break; default:break; } }//***************************************************************按下P36按键,触发中断,会让displayflag=1,才显示数据,显示完之后,displayflag=0。 if(displayflag==1) { OLED_ShowNum(0,4,miao,5,12); // distance=maichongnum*0.05*zhouchang; 1圈242.76?,一圈20个格子,总格子数N,/20=圈数,一圈是一个周长,pi*D=3.14*65mm=204.1mm=20.4cm //N/20*20.4cm=N*1.02 distance=maichongnum*1.02; //cm sprintf(disbuf,"%0.2f",distance); OLED_ShowString(0,2, disbuf); displayflag=0; }//**********************如果开始标记等于1,说明按下启动键key,这时候小车才开始跑 if(startflag==1) { //开始循迹,请看这部分代码,太长了,单独拉出来写,方便看主程序逻辑 trackline0(); } if(startflag2==1) //蓝牙控制的循迹小车 { //开始循迹,请看这部分代码,太长了,单独拉出来写,方便看主程序逻辑 trackline1(); } // } }// //*****************************************************************************************下面是前面声明的函数的具体定义 // //**************************************************************//函数定义trackline0(); // //**************************************************************功能:按键循迹; void trackline0() { //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第1种情况 if(L1S==blackline & & L0S==whiteline& & MS==whiteline & & R0S==whiteline& & R1S==whiteline)//1 0 0 0 0 { qianjin(vturnsmallM,vturnbigM); //左da转弯,转到碰到中线停止 IT1 = 0; //关闭INT1下降沿中断,P33引脚是INT1 EX1 = 0; TR0 = 0; //定时器0关闭计时,同时把定时器0的中断关闭 ET0=0; AUXR |= 0x10; //这个在后面进入死循环,开启定时器2开始计时50ms,当超过1000ms=1s时间,仍然找不到黑线,也退出循环 while(overtime2flag!=0) { if(MS==blackline)break; } overtime2flag=0; //等待时间清0,后期可以再次使用,同时关闭T2 AUXR & = 0xef; //关闭定时器T2 IT1 = 1; //INT1下降沿中断,P33引脚是INT1 EX1 = 1; TR0 = 1; //定时器0计时,同时把定时器0的中断关闭 ET0=1; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第2种情况 else if(L1S==whiteline & & L0S==blackline& & MS==whiteline & & R0S==whiteline& & R1S==whiteline)//0 1 0 0 0 { qianjin(vturnsmall,vturnbig); //左xiao转弯 } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第3种情况 else if(L1S==whiteline & & L0S==whiteline& & MS==blackline & & R0S==whiteline& & R1S==whiteline)//00 1 0 0 { qianjin(vleftmove,vrightmove); //直走 } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第4种情况 else if(L1S==whiteline & & L0S==whiteline& & MS==whiteline & & R0S==blackline& & R1S==whiteline)//0 0 0 1 0 { qianjin(vturnbig,vturnsmall); //左xiao转弯vturnbig vturnsmall } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第5种情况 else if(L1S==whiteline & & L0S==whiteline& & MS==whiteline & & R0S==whiteline& & R1S==blackline)//0 0 0 0 1 { qianjin(vturnbigM ,vturnsmallM); //左da转弯vturnbigMvturnsmallM,碰到黑线,不然一直大转弯, //同时,打开定时器T2,关闭T0计算时间和INT1计算距离,只是进行计算时间,超时间就退出 //0001 0000 IT1 = 0; //关闭INT1下降沿中断,P33引脚是INT1 EX1 = 0; TR0 = 0; //定时器0关闭计时,同时把定时器0的中断关闭 ET0=0; AUXR |= 0x10; //这个在后面进入死循环,开启定时器2开始计时50ms,当超过1000ms=1s时间,仍然找不到黑线,也退出循环 while(overtime2flag!=0) { if(MS==blackline)break; } overtime2flag=0; //等待时间清0,后期可以再次使用,同时关闭T2 AUXR & = 0xef; //关闭定时器T2 IT1 = 1; //INT1下降沿中断,P33引脚是INT1 EX1 = 1; TR0 = 1; //定时器0计时,同时把定时器0的中断关闭 ET0=1; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第6种情况 elseif(L1S==blackline & & L0S==blackline & & R1S==whiteline )//11xx0 判断是左转90度 {IT1 = 0; //INT1下降沿中断,P33引脚是INT1 EX1 = 0; TR0 = 0; //定时器0计时,同时把定时器0的中断关闭 ET0=0; stop(); delay_tms(500); qianjin(vturnsmall,vturnbig); //左转弯 delay_tms(500); AUXR |= 0x10; //这个在后面进入死循环,开启定时器2开始计时50ms,当超过1000ms=1s时间,仍然找不到黑线,也退出循环 while(overtime2flag!=0) { if(R0S==blackline)break; } overtime2flag=0; //等待时间清0,后期可以再次使用,同时关闭T2 AUXR & = 0xef; //关闭定时器T2 miao=miao+3; //补偿3秒时间; IT1 = 1; //INT1下降沿中断,P33引脚是INT1 EX1 = 1; TR0 = 1; //定时器0计时,同时把定时器0的中断关闭 ET0=1; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第7种情况 elseif( L1S==whiteline& & R0S==blackline & & R1S==blackline)//0xx11 判断是右转90度 { IT1 = 0; //INT1下降沿中断,P33引脚是INT1 EX1 = 0; TR0 = 0; //定时器0计时,同时把定时器0的中断关闭 ET0=0; stop(); delay_tms(1000); qianjin(vturnbig,vturnsmall); // delay_tms(200); AUXR |= 0x10; //这个在后面进入死循环,开启定时器2开始计时50ms,当超过1000ms=1s时间,仍然找不到黑线,也退出循环 while(overtime2flag!=0) { if(L0S==blackline)break; } overtime2flag=0; //等待时间清0,后期可以再次使用,同时关闭T2 AUXR & = 0xef; //关闭定时器T2 miao=miao+3; //补偿3秒时间; IT1 = 1; //INT1下降沿中断,P33引脚是INT1 EX1 = 1; TR0 = 1; //定时器0计时,同时把定时器0的中断关闭 ET0=1; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第8种情况 elseif(L1S==blackline & & L0S==blackline& & MS==blackline & & R0S==blackline)//1111x 判断是终点,调头,左轮反转,右轮正转,左转调头 { IT1 = 0; //INT1下降沿中断,P33引脚是INT1 EX1 = 0; TR0 = 0; //定时器0计时,同时把定时器0的中断关闭 ET0=0; qianjin(vleftmove,vrightmove); delay_tms(1000); stop(); delay_tms(1000); turnback(vleftmove,vrightmove); delay_tms(800); TR0=0; AUXR |= 0x10; //这个在后面进入死循环,开启定时器2开始计时50ms,当超过1000ms=1s时间,仍然找不到黑线,也退出循环 while(overtime2flag!=0) { if(MS==blackline)break; } overtime2flag=0; //等待时间清0,后期可以再次使用,同时关闭T2 AUXR & = 0xef; //关闭定时器T2 miao=miao+5; //补偿5秒时间; IT1 = 1; //INT1下降沿中断,P33引脚是INT1 EX1 = 1; TR0 = 1; //定时器0计时,同时把定时器0的中断关闭 ET0=1; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第9种情况 这是极端情况,放在最后面判断 //000找不到直线,如果前面是直走,就转360度,如果是之前右边,就左转,之前左偏,就右转 elseif(L1S==whiteline & & L0S==whiteline & & MS==whiteline & & R0S==whiteline & & R1S==whiteline) { qianjin(vturnbig,vturnsmall); // }}// //****************************************************************************************************+++++*//函数定义trackline1(); // //**************************************************************功能:按键循迹; void trackline1() { //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第1种情况 if(L1S==blackline & & L0S==whiteline& & MS==whiteline & & R0S==whiteline& & R1S==whiteline)//1 0 0 0 0 { qianjin(vturnsmallM,vturnbigM); //左da转弯,转到碰到中线停止 IT1 = 0; //关闭INT1下降沿中断,P33引脚是INT1 EX1 = 0; TR0 = 0; //定时器0关闭计时,同时把定时器0的中断关闭 ET0=0; AUXR |= 0x10; //这个在后面进入死循环,开启定时器2开始计时50ms,当超过1000ms=1s时间,仍然找不到黑线,也退出循环 while(overtime2flag!=0) { if(MS==blackline)break; } overtime2flag=0; //等待时间清0,后期可以再次使用,同时关闭T2 AUXR & = 0xef; //关闭定时器T2 IT1 = 1; //INT1下降沿中断,P33引脚是INT1 EX1 = 1; TR0 = 1; //定时器0计时,同时把定时器0的中断关闭 ET0=1; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第2种情况 else if(L1S==whiteline & & L0S==blackline& & MS==whiteline & & R0S==whiteline& & R1S==whiteline)//0 1 0 0 0 { qianjin(vturnsmall,vturnbig); //左xiao转弯 } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第3种情况 else if(L1S==whiteline & & L0S==whiteline& & MS==blackline & & R0S==whiteline& & R1S==whiteline)//00 1 0 0 { qianjin(vleftmove,vleftmove); //直走 } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第4种情况 else if(L1S==whiteline & & L0S==whiteline& & MS==whiteline & & R0S==blackline& & R1S==whiteline)//0 0 0 1 0 { qianjin(vturnbig,vturnsmall); //左xiao转弯vturnbig vturnsmall } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第5种情况 else if(L1S==whiteline & & L0S==whiteline& & MS==whiteline & & R0S==whiteline& & R1S==blackline)//0 0 0 0 1 { qianjin(vturnbigM ,vturnsmallM); //左da转弯vturnbigMvturnsmallM,碰到黑线,不然一直大转弯, //同时,打开定时器T2,关闭T0计算时间和INT1计算距离,只是进行计算时间,超时间就退出 //0001 0000 IT1 = 0; //关闭INT1下降沿中断,P33引脚是INT1 EX1 = 0; TR0 = 0; //定时器0关闭计时,同时把定时器0的中断关闭 ET0=0; AUXR |= 0x10; //这个在后面进入死循环,开启定时器2开始计时50ms,当超过1000ms=1s时间,仍然找不到黑线,也退出循环 while(overtime2flag!=0) { if(MS==blackline)break; } overtime2flag=0; //等待时间清0,后期可以再次使用,同时关闭T2 AUXR & = 0xef; //关闭定时器T2 IT1 = 1; //INT1下降沿中断,P33引脚是INT1 EX1 = 1; TR0 = 1; //定时器0计时,同时把定时器0的中断关闭 ET0=1; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第6种情况 elseif(L1S==blackline & & L0S==blackline & & R1S==whiteline )//11xx0 判断是左转90度 {IT1 = 0; //INT1下降沿中断,P33引脚是INT1 EX1 = 0; TR0 = 0; //定时器0计时,同时把定时器0的中断关闭 ET0=0; stop(); delay_tms(500); qianjin(vturnsmall,vturnbig); //左转弯 delay_tms(500); AUXR |= 0x10; //这个在后面进入死循环,开启定时器2开始计时50ms,当超过1000ms=1s时间,仍然找不到黑线,也退出循环 while(overtime2flag!=0) { if(R0S==blackline)break; } overtime2flag=0; //等待时间清0,后期可以再次使用,同时关闭T2 AUXR & = 0xef; //关闭定时器T2 miao=miao+3; //补偿3秒时间; IT1 = 1; //INT1下降沿中断,P33引脚是INT1 EX1 = 1; TR0 = 1; //定时器0计时,同时把定时器0的中断关闭 ET0=1; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第7种情况 elseif( L1S==whiteline& & R0S==blackline & & R1S==blackline)//0xx11 判断是右转90度 { IT1 = 0; //INT1下降沿中断,P33引脚是INT1 EX1 = 0; TR0 = 0; //定时器0计时,同时把定时器0的中断关闭 ET0=0; stop(); delay_tms(1000); qianjin(vturnbig,vturnsmall); // delay_tms(200); AUXR |= 0x10; //这个在后面进入死循环,开启定时器2开始计时50ms,当超过1000ms=1s时间,仍然找不到黑线,也退出循环 while(overtime2flag!=0) { if(L0S==blackline)break; } overtime2flag=0; //等待时间清0,后期可以再次使用,同时关闭T2 AUXR & = 0xef; //关闭定时器T2 miao=miao+3; //补偿3秒时间; IT1 = 1; //INT1下降沿中断,P33引脚是INT1 EX1 = 1; TR0 = 1; //定时器0计时,同时把定时器0的中断关闭 ET0=1; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第8种情况 elseif(L1S==blackline & & L0S==blackline& & MS==blackline & & R0S==blackline)//1111x 判断是终点,调头,左轮反转,右轮正转,左转调头 {stop(); //等待蓝牙控制走过断线区域 } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++第9种情况 这是极端情况,放在最后面判断 //000找不到直线,如果前面是直走,就转360度,如果是之前右边,就左转,之前左偏,就右转 elseif(L1S==whiteline & & L0S==whiteline & & MS==whiteline & & R0S==whiteline & & R1S==whiteline) { qianjin(vturnbig,vturnsmall); // }} //******************************************************************************中断函数不需要声明,直接使用; void INT0_Isr() interrupt 0 using 1//外部中断0,金属接触 { unsigned char i; IT1 = 0; //关闭测距离的传感器INT1下降沿中断,P33引脚是INT1 EX1 = 0; TR0 = 0; //定时器0关闭计时 stop(); delay_tms(1000); for(i=0; i< 5; i++) { led=0; beep=1; delay_tms(1000); led=1; beep=0; delay_tms(1000); } miao=miao+11; //补充11秒的时间 IT1 = 1; //测距离的传感器打开INT1下降沿中断,P33引脚是INT1 EX1 = 1; TR0 = 1; //定时器0计时 qianjin(vleftmove,vrightmove); //直走,走出金属区域 } //****************************************************************************外部中断1,测量脉冲的个数 void INT1_Isr() interrupt 2 using 1 { maichongnum++; //测试端口} //****************************************************************************外部中断2,按下按键,显示数据,不按,就不显示数据 void INT2_Isr() interrupt 10 using 1 { P00=!P00; //测试端口 displayflag=1; } //****************************************************************************************************** //**************************************************************************定时1s,计算启动的时间 void TM0_Isr() interrupt 1 using 1 { static unsigned char countT0num=0; TL0 = 0x00; //设置定时初值 TH0 = 0x4C; //设置定时初值 countT0num++; //50ms加一次 if(countT0num> =20)//1秒时间到 {countT0num=0; miao=miao+1; if(miao> 600)//最大设置,计算到600秒 miao=0; }} //************************************************************************//*********************************************************************50ms进入一次,定时器2中断函数,50ms*20=1s,超时设置为1s void TM2_Isr() interrupt 12 using 1 { static unsigned char countT2num=0; countT2num++; if(countT2num> =20) { countT2num=0; overtime2flag=1; } AUXINTIF & = ~T2IF; //清中断标志 }//******************************************************************** /************************************************************************/ void UartIsr() interrupt 4 using 1//中断接收3个字节,\'0\'+第一个数据+第二个数据 { if(RI)//是否接收中断 { RI=0; cmddat=SBUF; if(cmddat==\'O\'& & (cmdnum==0)) //接收数据第一帧 { cmdbuff[cmdnum]=cmddat; cmdflag=1; //开始接收数据 } else if(cmdflag==1)//如果不是第一个数据,说明帧头校验通过,就继续接收, { cmdnum++; cmdbuff[cmdnum]=cmddat; if(cmdnum> =2) { cmdnum=0; cmdflag=0; cmdflag_REC=1; // 停止接收 } } } }


    推荐阅读