/**
AVR mega128
8M晶振
本程序使用了F口作为12864的数据口,故下载程序前应该把JTAG功能关闭
***/
#include<mega128.h>
#include <delay.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
//LCD 端口定义
#define E PORTA.2
#define RW PORTA.1
#define RS PORTA.0
#define PSB PORTA.3
#define RST PORTA.4
#define LCD_Data PORTF
//超声波 端口定义
#define TRING PORTA.5
#define ECHO PINE.7
//变量定义
ulong ov_counter=0;
uint rising_edge,falling_edge;
ulong pulse_clocks;
ulong echo_data;
double speed;
uint temp;
unsigned char flash numlist[]="0123456789";
unsigned char flash addrlist[32]=
{0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f};
void Init_Port();
void Init_Reg();
void Echo_scan();
void Celiang();
void Lcd_Init(); //12864初始化
void Lcd_Write_Str(unsigned char flash *s) ; //12864写汉字
void Lcd_Write_Cmd(uchar com); //12864写数据
void Lcd_Write_Data(uchar dat); //12864写数据
void LcmPrint(unsigned char x,unsigned char y,unsigned char flash *adata);
void Lcd_WriteNum(uchar i,uchar j,ulong number);
void Jiemian()
{
Lcd_Write_Cmd(0x88);
Lcd_Write_Str("距离:");
Lcd_Write_Cmd(0x88+6);
Lcd_Write_Str("mm");
delay_ms(60);
}
void main()
{
Init_Port(); //端口初始化
Init_Reg(); //寄存器初始化
Lcd_Init(); //12864液晶初始化
Jiemian(); //画出基本界面
//使能T/C3 扑捉中断
while(1)
{
Echo_scan(); //超声波模块启动测量
Celiang(); //计算距离
Lcd_WriteNum(3,4,echo_data); //显示距离
}
}
//*************超声波扫描**********
void Echo_scan()
{
TRING=1;
delay_us(20);
TRING=0;
}
void Celiang()
{
pulse_clocks=(double)pulse_clocks;
echo_data=pulse_clocks*0.340/2-18; //
}
//*****************中断服务程序******************
interrupt [TIM3_OVF] void Timer3_ovf_isr()
{
ov_counter++;
}
interrupt [TIM3_CAPT] void Timer3_capt_isr()
{
if(ECHO){
rising_edge=ICR3L;
temp=ICR3H;
rising_edge|=temp<<8;
TCCR3B&=0xbf;
ov_counter=0;
}
else{
falling_edge=ICR3L;
temp=ICR3H;
falling_edge|=temp<<8;
TCCR3B|=0x40;
pulse_clocks=(ulong)falling_edge-(ulong)rising_edge
+(ulong)ov_counter*0x10000;
}
}
//////////////////////////////////////
void Lcd_Init()
{
RST=0;
delay_ms(100);
RST=1;
Lcd_Write_Cmd(0x30); //选择基本指令集
//选择8bit数据流
Lcd_Write_Cmd(0x03);
Lcd_Write_Cmd(0x01); //清除显示,并且设定地址指针为00H
Lcd_Write_Cmd(0x0c); //开显示(无游标、不反白)
}
void Init_Port()
{
PORTE=0XFF;
DDRE=0X7F; //PORE.7超声波信号输入
PORTF=0xff;
DDRF=0xff;
PORTA=0xff;
DDRA=0xff;
}
void Init_Reg()
{
TCCR3B=0X42;
ETIMSK=0X24;
#asm("sei");
}
void Lcd_WriteNum(uchar i,uchar j,ulong number)/*在第i行第j列开始写3位数据*/
{
uchar a,b,c,d,e,f,g;
//a=number/1000000;
//b=(number%1000000)/100000;
c=(number%100000)/10000;
d=(number%10000)/1000;
e=(number%1000)/100;
f=(number%100)/10;
g=number%10;
Lcd_Write_Cmd(addrlist[8*i+j-9]);
//Lcd_Write_Data(numlist[a]);
//Lcd_Write_Data(numlist[b]);
Lcd_Write_Data(numlist[c]);
Lcd_Write_Data(numlist[d]);
Lcd_Write_Data(numlist[e]);
Lcd_Write_Data(numlist[f]);
Lcd_Write_Data(numlist[g]);
}
//在坐标(x,y)处显示字符串
void LcmPrint(unsigned char x,unsigned char y,unsigned char flash *adata)
{
if((y>3)||(x>7))
return;//如果指定位置不在显示区域内,则不做任何写入直接返回
switch(y)
{
case 0:
Lcd_Write_Cmd(0x80+x);
break;
case 1:
Lcd_Write_Cmd(0x90+x);
break;
case 2:
Lcd_Write_Cmd(0x88+x);
break;
case 3:
Lcd_Write_Cmd(0x98+x);
break;
}
while(*adata>0)
{
Lcd_Write_Data(*adata); ////写8位的字符数据
adata++; ////指针指向下一个地址单元
}
}
unsigned char Lcd_CheckBusy(void)
{
unsigned char Busy;
LCD_Data=0xff;
RS=0;
RW=1;
E=1;
delay_us(1);
Busy=LCD_Data&0x80;
E=0;
return Busy;
}
/***********************************
从LCD中读出数据
************************************/
unsigned char Lcd_ReadData(void)
{
unsigned char Temp;
while(Lcd_CheckBusy());
LCD_Data=0xff;
RS=1;
RW=1;
E=1;
delay_us(1);
Temp=LCD_Data;
E=0;
return Temp;
}
//-------------12864写数据函数-----------------
void Lcd_Write_Data(uchar dat)
{
delay_ms(3);
RS=1;
RW=0;
E=1;
LCD_Data=dat;
E=0;
}
//-------------12864写命令函数----------------
void Lcd_Write_Cmd(uchar com)
{
delay_ms(5);
RS=0;
RW=0;
E=1;
LCD_Data=com;
E=0;
}
//-------------12864显示写汉字函数---------------
void Lcd_Write_Str(unsigned char flash *s)
{ while(*s>0)
{ Lcd_Write_Data(*s);
s++;
delay_ms(1);// 原文是 delay(50);
}
}