14、吴鉴鹰单片机项目详细解析系列(连载)之基于单片机的超声波测距仪设计(四)——软件设计(二)
/**********************************************************************************
** 函数名称: void lcd_pos(uchar X,uchar Y)
** 功能描述: 设定显示位置
** 输 入: uchar X,uchar Y
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void lcd_pos(uchar X,uchar Y)
{
uchar pos;
if (X==1)
{
X=0x80;
}
else
if (X==2)
{
X=0x90;
}
else
if (X==3)
{
X=0x88;
}
else
if (X==4)
{
X=0x98;
}
pos = X+Y ;
write(0,pos); //lcd_wcmd(pos); //写位置命令
}
/**********************************************************************************
** 函数名称: show(uint ss)
** 功能描述: 显示测试数据
** 输 入: uint ss
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void show(uint ss)
{
uchar data_s[2],i;
data_s[0]=ss/10000; //数据的处理
if(data_s[0]==0) //测量数据的十米位为0
{
data_s[0]=0x20;
}
else
{
data_s[0]=data_s+0x30; //
}
data_s[1]=ss%10000/1000+0x30;
lcd_pos(3,5); //第三行,第七个(2*n+1)字节位置显示
write(1,data_s[1]); //for(i=0;i<2;i++)
//{
// write(1,data_s); //lcd_wdat(data_s); //显示米位数据
//delay(1);
// }
data_s[0]=ss%1000/100+0x30;
data_s[1]=ss%100/10+0x30;
lcd_pos(3,6);
for(i=0;i<2;i++)
{
write(1,data_s); //lcd_wdat(data_s); //显示分米和厘米位数据
delay(1);
}
write(1,ss%10+0x30); //lcd_wdat(ss%10+0x30); //显示毫米位数据
delay(1);
}
/**********************************************************************************
** 函数名称: void lcd_init()
** 功能描述: 初始化LCD
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void lcd_init()
{
delay_lcd(10); //延时等待LCM进入工作状态
LCD_RS_OUT=1; //片选 高电平有效
write(0,0x30); //基本指令操作
write(0,0x0c); //显示打开,光标关,反白关
write(0,0x01); //清屏,将DDRAM的地址计数器归零
write(0,0x06);
}
/**********************************************************************************
** 函数名称: void photodisplay(uchar *bmp)
** 功能描述: uchar *bmp
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void photodisplay(uchar *bmp)
{
uchar i,j;
write(0,0x34); //写数据时,关闭图形显示
for(i=0;i<32;i++)
{
write(0,0x80+i); //先写入水平坐标值
write(0,0x80); //写入垂直坐标值
for(j=0;j<16;j++) //再写入两个8位元的数据
write(1,*bmp++);
delay_lcd(1);
}
for(i=0;i<32;i++)
{
write(0,0x80+i);
write(0,0x88);
for(j=0;j<16;j++)
write(1,*bmp++);
delay_lcd(1);
}
write(0,0x36); //写完数据,开图形显示
}
/**********************************************************************************
** 函数名称: void clr_screen()
** 功能描述: LCD清屏函数
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void clr_screen()
{
write(0,0x34); //lcd_wcmd(0x34); //扩充指令操作
delay(5);
write(0,0x30); //lcd_wcmd(0x30); //基本指令操作
delay(5);
write(0,0x01); //lcd_wcmd(0x01); //清屏
delay(5);
}
/**********************************************************************************
** 函数名称: void displayall()
** 功能描述: 主显示函数
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void displayall()
{
uchar i;
delay(2);
lcd_init(); //初始化LCD
lcd_pos(2,0); //设置显示位置为第二行
for(i=0;i<16;i++)
{
write(1,DIS9); //lcd_wLCD_RW_OUT(DIS9);
delay(30);
}
lcd_pos(3,0); //设置显示位置为第三行
for(i=0;i<16;i++)
{
write(1,DIS10); //lcd_wLCD_RW_OUT(DIS10);
delay(30);
}
delay(1000);
clr_screen(); //清屏
delay(500);
clr_screen(); //上电,等待稳定
lcd_pos(1,0); //设置显示位置为第一行
for(i=0;i<16;i++)
{
write(1,DIS1); //lcd_wLCD_RW_OUT(DIS1);
delay(2);
}
lcd_pos(3,0); //设置显示位置为第三行
for(i=0;i<16;i++)
{
write(1,DIS3); //lcd_wLCD_RW_OUT(DIS3);
delay(2);
}
lcd_pos(4,0); //设置显示位置为第四行
for(i=0;i<16;i++)
{
write(1,DIS8); //lcd_wLCD_RW_OUT(DIS8);
delay(2);
}
delay(1000);
}
/**********************************************************************************
** 函数名称: void show_one(uchar DIS[8],uchar hh)
** 功能描述: 设置行显示
** 输 入: uchar DIS[16],uchar hh
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void show_one(uchar DIS[16],uchar hh)
{
uchar i;
lcd_pos(hh,0); //设置显示位置行
for(i=0;i<16;i++)
{
write(1,DIS); //lcd_wLCD_RW_OUT(DIS);
delay(1);
}
}
/**********************************************************************************
** 函数名称: void send_com(uchar add)
** 功能描述: 发码播放,add为语音地址
** 输 入: uchar add
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void send_com(uchar add)
{
uchar i;
LCD_RST_OUT=1;
LCD_RST_OUT=0;
delay_nms(3);
LCD_RST_OUT=1;
delay_nms(20);
LCD_RS_OUT=0;
delay_nms(5);
for(i=0;i<8;i++)
{
LCD_CLK_OUT=0;
if(add&1) LCD_RW_OUT=1;
else LCD_RW_OUT=0;
delay100us();
LCD_CLK_OUT=1;
delay100us();
add=add>>1;
}
LCD_RS_OUT=1;
}
/**********************************************************************************
** 函数名称: void sound(uint soud)
** 功能描述: 播报测距距离
** 输 入: soud
**
**
** 输 出:
**
** 全局变量:
** 调用模块:
**
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void sound(uint soud)
{
uchar i,j,k,l;
send_com(vo_vo);
while(!WT_busy_OUT);
i=soud/1000;
j=soud%1000/100;
k=soud%100/10;
l=soud%10;
send_com(i);
delay_nms(30);
while(!WT_busy_OUT);
send_com(10); //播放“点”
delay_nms(30);
while(!WT_busy_OUT);
send_com(j);
delay_nms(30);
while(!WT_busy_OUT);
send_com(k);
delay_nms(30);
while(!WT_busy_OUT);
if(l!=0)
{
send_com(l);
delay_nms(30);
while(!WT_busy_OUT);
}
send_com(11); //播放"米"
delay_nms(30);
while(!WT_busy_OUT);
}
/**********************************************************************************
** 函数名称: void dis_all(uint dis_s)
** 功能描述: 控制LED指示灯和语音播报
** 输 入: uint dis_s
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void dis_all(uint dis_s)
{
show(dis_s);
if(dis_s>2000)
{
show_one(DIS4,2);
LED_green_OUT=0;LED_red_OUT=1;LED_yellow_OUT=1;
if(flag_2!=1)
{
}
flag_2=1;
}
else
{
if((dis_s>500)&(dis_s<1000))
{
show_one(DIS5,2);
LED_green_OUT=1;LED_red_OUT=1;LED_yellow_OUT=0;
if(flag_2!=2)
{
}
flag_2=2;
}
else
{
if((dis_s>100)&(dis_s<500))
{
show_one(DIS6,2);
LED_green_OUT=1;LED_red_OUT=0;LED_yellow_OUT=1;
if(flag_2!=3)
{
}
flag_2=3;
}
else
{
show_one(DIS8,2);
LED_yellow_OUT=1;
if(dis_s<100)
{ LED_red_OUT=!LED_red_OUT;LED_green_OUT=1;}
else
{LED_green_OUT=!LED_green_OUT;LED_red_OUT=1;}
}
}
}
}
/**********************************************************************************
** 函数名称: void Disp_Temperature()
** 功能描述: 显示温度
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void Disp_Temperature()//显示温度
{
unsigned char n=0, word[16]={"环境温度: ℃"};
show_one(word,4);
for(n=0;n<16;n++)
write(1,word[n]);
lcd_pos(4,5); //设置显示位置为第三行
if(display_TEMP_DATA[3] != 0)
write(1,display_TEMP_DATA[3]+0x30); //lcd_wdat(display_TEMP_DATA[3]+0x30); //温度值百位不显示
else
write(1,0x20); //lcd_wdat(0x20); */
delay(1);
if((display_TEMP_DATA[3]==0)&&(display_TEMP_DATA[2]==0))
{
write(1,0x20); //lcd_wdat(0x20);
}
else
{
write(1,display_TEMP_DATA[2]+0x30); //lcd_wdat(display_TEMP_DATA[2]+0x30);
}
delay(1);
write(1,display_TEMP_DATA[1]+0x30); //lcd_wdat(display_TEMP_DATA[1]+0x30);
delay(1);
write(1,'.'); //lcd_wdat('.');
delay(1);
write(1,display_TEMP_DATA[0]+0x30); //lcd_wdat(display_TEMP_DATA[0]+0x30);
delay(1);
}
/**********************************************************************************
** 函数名称: void soundplay(uint dis_say)
** 功能描述: 播放“测量距离"
** 输 入: uint dis_say(测得的距离)
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void soundplay(uint dis_say)
{
if(WT_busy_OUT != 0)
{
sound(dis_say);//播放“测量距离”
}
}
/**********************************************************************************
** 函数名称: void USART_init(void)
** 功能描述: 播放“测量距离"
** 输 入: uint dis_say(测得的距离)
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void USART_init(void) //串口的初始化
{
TH1=0xfd;
TL1=0xfd;
TR1=1;
SM0=0;
SM1=1;
REN=1;
}
/**********************************************************************************
** 函数名称: void dists_data_mov(uchar dat)
** 功能描述: 将受到的数值转换成LCD12864能显示的数据,存放到相应的数组中,dist_test_DATA为距离的
display_TEMP_DATA为温度数组
** 输 入: uint dat
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void dists_data_mov(uchar dat)
{
if(dat == 1)
{
point4[0] = ((uint)(dist_test_DATA[0]<<8 + dist_test_DATA[1]))/10000;
point4[1] = ((uint)(dist_test_DATA[0]<<8+ dist_test_DATA[1]))/1000%10;
point4[2] = ((uint)(dist_test_DATA[0]<<8+ dist_test_DATA[1]))/100%10;
point4[3] = ((uint)(dist_test_DATA[0]<<8+ dist_test_DATA[1]))/10%10;
point4[4] = ((uint)(dist_test_DATA[0]<<8+ dist_test_DATA[1]))%10;
}
else
{
space4[0] = ((uint)display_TEMP_DATA[2]<<8+ display_TEMP_DATA[3])/10000;
space4[1] = ((uint)display_TEMP_DATA[2]<<8+ display_TEMP_DATA[3])/1000%10;
space4[2] = ((uint)display_TEMP_DATA[2]<<8+ display_TEMP_DATA[3])/100%10;
space4[3] = ((uint)display_TEMP_DATA[2]<<8+ display_TEMP_DATA[3])/10%10;
space4[4] = ((uint)display_TEMP_DATA[2]<<8+ display_TEMP_DATA[3])%10;
}
}
/**********************************************************************************
** 函数名称: void soundplay(uint dis_say)
** 功能描述: 播放“测量距离"
** 输 入: uint dis_say(测得的距离)
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void main(void)
{
uchar i,j;
P0 = 0xff;
P1 = 0xff;
P2 = 0xff;
TMOD=0x21;
TH0=0;
TL0=0;
EA=1;
IE=0x90;
IT1=0;
USART_init(); //串口的初始化
Num = 0;
while(1)
{
//* if(tc_say==4)
//{
//temp_all(); 温度补偿
//tc_say=0;
//}*/
/*tc_say++;
//for(i=0;i<9;i++)
//{
// IE=0x80;
// tran1();
// dis = do_s(dis);
// dis_4 = dis;
//}
//fit_1();*/
//*if(dis4000) time=time-1000;
//else
//{
// if((time-dis)<2500) time=dis;
// else time=time-100;
//}
//}
//else*/
Disp_Temperature();//温度显示
dists_data_mov(0); //温度示数转换
dists_data_mov(1); //距离示数转换
dis_all(dis); //语音播报
dis=0;
lcd_pos(1,6); //设定显示位置
for(j=0;j<4;j++)
write(1,space4[j]);
lcd_pos(1,6); //设定显示位置
for(j=0;j<4;j++)
{
write(1,point4[j]);
delay(100);
}
}
}
/**********************************************************************************
** 函数名称: void ser() interrupt 4
** 功能描述: 串口中断接收数据
** 输 入:
** 输 出:
** 全局变量:
** 调用模块:
** 作 者: 吴鉴鹰
** 日 期: 14.03.5
************************************************************************************/
void ser() interrupt 4 //中断接收数据
{
unsigned char receive[10];
unsigned char a,i;
if(RI==1)
{
DIS_receive_data[Num] = SBUF;
if(Num < 5)
{
Num++;
}
else
{
a = receive[0];
for(i = 1;i < 4;i ++)
{
a = a&receive;
}
if(a = receive[4])
{
for(i = 0; i < 2;i++)
{
display_TEMP_DATA = receive;
}
for(i = 2;i < 4;i++)
{
dist_test_DATA = receive;
}
}
/*if(DIS_receive_data[0]&DIS_receive_data[1] == DIS_receive_data[2])
{
}*/
Num = 0;
}
flag=1;
RI=0;
}
}