📄 12.c
字号:
/**********************************************
显示和键盘都已经正常,键盘采用的是中断方式
2008.7.2
**************************************/
#include <P89V51.h>
#include <absacc.h>
#include <intrins.h>
#include <stdlib.h>
#include <stdio.h>
#define uchar unsigned char
//SYSTEM ADDRESS ALLOCATION ******************
#define KEYCOLUM XBYTE[0xEFFF]
#define KEYROW XBYTE[0xDFFF]
#define ALARM XBYTE[0xCFFF]
#define HC245C1 XBYTE[0xBFFF]
#define HC245C2 XBYTE[0xAFFF]
#define HC573C1 XBYTE[0x9FFF]
#define HC573C2 XBYTE[0x8FFF]
#define HC573C3 XBYTE[0x7FFF]
#define ADCS XBYTE[0x6FFF]
#define DACS XBYTE[0x5FFF]
#define DACLOAD XBYTE[0x4FFF]
//***************************************
//static unsigned char keyin=0;
/*-------------LCD1602 definitions and functions--------------*/
#define nops() {_nop_();_nop_();_nop_();}
typedef bit BOOL;
#define FALSE (bit)0
#define TRUE (bit)1
sbit lcd_cs = P2^0; //控制位
sbit lcd_rw = P2^1;
sbit lcd_rs = P2^2;
#define DataPort P0
#define DataDirPort P0
#define StatePort P0
#define Busy 0x80 // 忙判别位
uchar keystate,keyin=0;
char n=0,i,flag=0,c_2;
unsigned int a, ADs,ch;
char ADval[10];
//**************时间变量**********************
unsigned int tick=0,second=0,second_1=0,minute=0,b_out,c_0,c_1,mid,mid2,ch,ch_0=0,ch_no=0;
//*****************控制变量*********************
unsigned int step=0,t_1=0,t_2,t_3,t_no=0,co_2;
float co_1;
void delay(long t)
{
while(t)
t--;
}
code unsigned char* WrtieLcdErr = "Display char outof range.";
// ------ Private function prototypes --------------------------
static BOOL WaitTillNotBusy();
static BOOL LocateXY(unsigned char posx, unsigned char posy);
static BOOL LcdWData(unsigned char dataW);
static BOOL LcdWCMD(unsigned char CMD);
BOOL LCDInit() ;
BOOL DisplayOneChar(unsigned char x ,unsigned char y ,unsigned char Wdata) ;
BOOL DisplayString(unsigned char posx, unsigned char posy, unsigned char* str);
unsigned char keyscan(void);
unsigned char Gatkey(char keystate);
BOOL WaitTillNotBusy()
{
unsigned int delay = 0xffff;
DataDirPort = 0xff;
lcd_cs = 1;
lcd_rs = 0;
lcd_rw = 1;
while( (StatePort & Busy) && delay)
delay--;
lcd_cs = 0;
if (!delay)
return FALSE ;
return TRUE;
}
BOOL LocateXY( unsigned char posx,unsigned char posy)
{
posy &= 0x01;
if (posy == 1)
posx |= 0x40;
posx |= 0x80;
return LcdWCMD(posx);
}
BOOL LcdWCMD(unsigned char CMD)
{
unsigned char i=1;
if (!WaitTillNotBusy()) // 检测忙信号?
return FALSE;
DataPort = CMD;
lcd_rs = 0;
lcd_rw = 0;
lcd_cs = 1;
while(i++);
lcd_cs = 0;
return TRUE;
}
BOOL LcdWData( unsigned char dataW )
{
unsigned char i = 1;
if (!WaitTillNotBusy()) // 检测忙信号?
return FALSE;
DataPort = dataW;
lcd_rs = 1;
lcd_rw = 0;
lcd_cs = 1;
while(i++);
lcd_cs = 0;
return TRUE;
}
// LCD输出用函数
//LCDInit--LCD初始化
//DisplayOneChar(x,y,char) --在指定x,y显示一个字符
//DisplayString(x,y,str)--在指定位置x,y开始显示一个字符串
BOOL LCDInit()
{
// 显示模式设置,光标移动设置,显示开及光标设置,显示清屏
return (LcdWCMD( 0x38) && LcdWCMD( 0x06) && LcdWCMD( 0x0c) && LcdWCMD( 0x01));
}
BOOL DisplayOneChar(unsigned char x ,unsigned char y ,unsigned char Wdata)
{
if( (x >= 0 && x < 16) && (y >= 0 && y < 2) )
return (LocateXY( x, y ) && LcdWData( Wdata )) ;// 定位显示地址,写字符
else
return ( LCDInit() && DisplayString(0, 0, WrtieLcdErr)); //显示越界消息
}
BOOL DisplayString(unsigned char posx, unsigned char posy, unsigned char* str)
{
while ( (*str) != '\0' )
{
if (!DisplayOneChar(posx, posy, (*str)))
return FALSE;
str++;
posx++;
if( posx == 16 )
{
posx = 0;
posy++;
}
}
return TRUE;
}
/*--------------End of LCD1602 macros and functions------------------*/
/*-------------- ----SPI protocols----------------------------------- */
void SpiInit(void)
{
SPCR = 0x51;
SPSR = 0x00;
}
void SpiClose(void) {SPCR = 0x00;}
/*----------------End of SPI protocols---------------------------*/
//-----------ADC MCP3208 functions--------------------
// ReadAD(chx)读AD,chx为通道号
//chx=0x00----0x07对应AD0---AD7通道
unsigned int ReadAD(unsigned char chx)
{
unsigned int lsb,msb;
char sbuf;
lsb=0;msb=0;
ADCS = 0x00;
sbuf = 0x06 | (chx>>2);
SPDAT = sbuf;
while(!(SPSR&0x80) );
SPSR = 0x00;
sbuf = SPDAT;
sbuf = (chx&0x03)<<6;
SPDAT = sbuf;
while(!(SPSR&0x80) );
SPSR = 0x00;
sbuf = SPDAT;
msb = sbuf&0x0F;
sbuf = 0x00;
SPDAT = sbuf;
while(!(SPSR&0x80) );
SPSR = 0x00;
lsb = SPDAT;
XBYTE[0xFFFF] = 0x00;
return msb*256+lsb;
}
//------------End ADC MCP3208 functions-----------------
//-----------------DAC MCP4922 functions----------------------
void DACout( unsigned char DACH, unsigned int DAValue)
{
unsigned char msb,lsb,temp;
XBYTE[0xFFFF] = 0;
DAValue&=0x0FFF;
temp = (DAValue/256)&0x0F;
DACS = 0x00;
if(DACH==1)
{
msb =0x70|temp;
lsb = (unsigned char)(DAValue & 0xFF) ;
}
else if(DACH==2)
{
msb =0xF0|temp;
lsb = (unsigned char)(DAValue & 0xFF) ;
}
else
{ }
SPDAT = msb;
while(!(SPSR&0x80) );
SPSR = 0x00;
SPDAT = lsb;
while(!(SPSR&0x80) );
SPSR = 0x00;
XBYTE[0xFFFF] = 0;
DACLOAD = 0x00;
nops();
XBYTE[0xFFFF] = 0;
}
//**********************按键中断响应**********************
void Int1_keyscan( ) interrupt 0
{
unsigned char ucSKey;
unsigned int uiI;
EA=0;
for (uiI=0;uiI<100;uiI++); //延时,去掉抖动
if(INT1==1)
goto end01;
for (uiI=0;uiI<100;uiI++); //延时,去掉抖动
if(INT1==1)
goto end01; //关闭外部中断
//LcdWCMD( 0x01) ; //显示清屏
keyscan(); //获取按键状态
Gatkey(keystate);
DisplayOneChar(0,1,keyin); //显示按键对应的字符
//delay(500);
while(P3_2==0){;}
delay(100);
while(P3_2==0){;}
end01:;
EA=1; // 开启中断
KEYROW=0x00;
}
//*****************获取按键状态函数******************
unsigned char keyscan(void)
{
uchar recode,sccode;
KEYROW=0xE0; //将行都设置为低电平
recode=KEYCOLUM; //获取列的状态
if((recode&0x0F)!=0x0F) //判断是否有键按下和延时去抖动
{
delay(6000);
if((recode&0x0F)!=0x0F)
{
sccode=0xFE; //设置行扫描的初始值
while((sccode&0x20)!=0) //判断并逐行扫描
{
KEYROW=sccode;
recode=KEYCOLUM;
if((recode&0x0F)!=0x0F)
{
recode=(recode&0x0F)|0xF0; //记录列号
sccode=~sccode; //记录行号
sccode=sccode<<4; //把行号方到高四位
keystate=(sccode)+(~recode); //记录行列状态,高四位为行号,低四位为列号
return keystate;
break;
}
else
sccode=(sccode<<1)|0x01; //行扫描后没找到按键状态则转到下一行
}
}
}
return(0);
}
//**********************按键对应的显示字符**********************************
unsigned char Gatkey(char keystate)
{
switch (keystate)
{
case 0x11: keyin='a';
break;
case 0x12: keyin='b';
break;
case 0x14: keyin='c';
break;
case 0x18: keyin='d';
break;
case 0x21: keyin='e';
break;
case 0x22: keyin='f';
break;
case 0x24: keyin='g';
break;
case 0x28: keyin='h';
break;
case 0x41: keyin='i';
break;
case 0x42: keyin='j';
break;
case 0x44: keyin='k';
break;
case 0x48: keyin='l';
break;
case 0x81: keyin='m';
break;
case 0x82: keyin='n';
break;
case 0x84: keyin='0';
break;
case 0x88: keyin='p';
break;
case 0x01: keyin='q';
break;
case 0x02: keyin='r';
break;
case 0x04: keyin='s';
break;
case 0x08: keyin='t';
break;
default: keyin='N' ;
}
return keyin;
}
void Setpwm(char channel, unsigned char pwmval)
{
switch (channel )
{
case 0:
CCAP0L = pwmval; //PWMVAL值确定占空比,0X00-0XFF;反比例:
CCAP0H = pwmval;CCAPM0 = 0x4A;
break;
case 1:
CCAP1L = pwmval;
CCAP1H = pwmval;CCAPM1 = 0x4A;
break;
default:
CCAP0L = pwmval;
CCAP0H = pwmval;CCAPM0 = 0x4A ;
}
}
//**********************子程序附加*******************
//***********************************
void stop(void)
{
HC573C1=0x00; //停止
}
void go_left(void)
{
HC573C1=0x01; //左转
}
void go_right(void)
{
HC573C1=0x04; //右转
}
void go(void)
{
HC573C1=0x05; //前进
}
//*************处理*****************
void deal_go(void)
{
mid=HC245C1%4; //寻迹读入
if(mid==2)go_left();
if(mid==1)go_right();
if(mid==3)go();
if(mid==0)
{
t_no++;
stop();
if((t_no==3)||(t_no==4))
{
while(mid==0)
{
go();
mid=HC245C1%4;
}
}
else
{
go();
delay(100);
while(mid==0)
{
go();
mid=HC245C1%4;
}
for(i=0;i<16;i++)
{
mid=HC245C1%4;
if(mid==2)go_left();
if(mid==1)go_right();
if(mid==3)go();
if(mid==0)go();
delay(100);
}
stop();
delay(60000);
HC573C2=0x00;
}
}
}
/*
void deal_go2(void)
{
if((P2_0==0)||(P2_1==0))
{
t_no++;
flag=1;
t_1=second_1;
}
}
*/
//******************时间显示**************************
void LCD_TIME(void)
{
DisplayString(11,0,"m s ");
sprintf(ADval,"%d",second);
DisplayString(13,0,ADval);
sprintf(ADval,"%d",minute);
DisplayString(10,0,ADval);
}
void LCD_cesu(void)
{
a=TH1*256+TL1;
sprintf(ADval,"%d",a);
if(a<10000)ADval[4]=' ';
if(a<1000)ADval[3]=' ';
if(a<100)ADval[2]=' ';
if(a<10)ADval[1]=' ';
DisplayString(10,1,ADval);
}
//********************************平衡************************
void T0INT( ) interrupt 1
{
EA=0;
TH0 = 0x3C;
TL0 = 0xAF;
tick ++;
if(tick>=19)
{
tick =0;
second++ ;
second_1++;
if(second>=60)
{
second=0;
minute++;
}
}
P1=0xff;
Setpwm(0,co_2);
EA=1;
}
//******************************主程序***************************
void main()
{
//int b,c;
SpiInit();
LCDInit();
DisplayString(5,1,"No= ");
HC573C1 = 0x0f;
HC573C2 = 0x0F;
KEYROW = 0x00;
P1 = 0x01;
//0x51--T0计时,T1计数
TMOD = 0x51; // 最高位置1测INTX脚高低电平长短,C/T位(第7位)置1选择计数模式 //*T1* GATE||C/T||M1||M0|*T0*|GATE||C/T||M1||M0||
TL0 = 0xAF;
TH0 = 0x3C;
TL1 = 0X00;
TH1 = 0X00;
ET0 = 1;
ET1 = 1;
TR0 = 1;
TR1 = 1;
EA = 1;
EX0 = 1;
CMOD = 0x02;
CCAPM0 = 0x4A;
CCAPM1 = 0x4A;
CL =0;
CCAP0H = 16;
CCON = 0x40;
// ADs = ReadAD(0x01);
// sprintf(ADval,"%d",ADs);
// DisplayString(0,0,ADval);
// DACout(1,ADs);
// DACout(2,ADs);
// KEYROW=0xE0;
//HC573C1 ^= 0x01;
// delay(10000); //这里加了延时会出现按键不正常
//HC573C1=0x01; //左转
//HC573C1=0x04; //右转
//HC573C1=0x05; //前进
//HC573C1=0x00; //停止
P1=0xff;
HC573C2 = 0xff;
while(keyin!='a'){;}
while(1)
{
deal_go();
LcdWCMD( 0x01) ; //显示清屏
a = TH1*256+TL1;
sprintf(ADval,"%d",a);
DisplayString(8,0,ADval);
sprintf(ADval,"%d",t_no);
DisplayString(0,1,ADval);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -