8.2.1 原理图
8.2.2 程序介绍
1. 8255连接如上图,下面是8255初始化和控制灯和开关的几个函数:
typedef unsigned char UINT8;
typedef unsigned int UINT16;
typedef unsigned long int UINT32;
#include
code unsigned char CLOSEOPEN[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
code unsigned char CLOSEOPENB[7]={0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
#define write_XDATA(address, value)
(*((unsigned char volatile pdata*)address) = value)//写外部存储器
/*15路开关控制、参数num表路数 flag表开关*/
void Contral8255(UINT8 num,bit flag)
{
data UINT8 temp;
if(num<7)
{
if(flag==1)
{
Pbvalue|=CLOSEOPENB[num];//&
}
else
{
temp=~CLOSEOPENB[num];
Pbvalue&=temp;//|
}
write_XDATA(0xf9,Pbvalue);
}
else if(num<15)
{
if(flag==1)
{
Pcvalue |=CLOSEOPEN[num-7];//&
}
else
{
temp=~CLOSEOPEN[num-7];
Pcvalue &=temp; //|
}
write_XDATA(0xfa,Pcvalue);
}
}
/*每路指示灯的开关、num相应路数的指示灯 flag表亮灭*/
void LedContral(UINT8 num,bit flag)
{
if(flag==1)
{
switch(num)
{
case 0:
Led1=0;
return;
case 1:
Led2=0;
return;
case 2:
Led3=0;
return;
case 3:
Led4=0;
return;
case 4:
Led5=0;
return;
case 5:
Led6=0;
return;
case 6:
Pavalue &=0xfe;
write_XDATA(0xf8, Pavalue);
return;
case 7:
Pavalue &=0xfd;
write_XDATA(0xf8, Pavalue);
return;
case 8:
Pavalue &=0xfb;
write_XDATA(0xf8, Pavalue);
return;
case 9:
Pavalue &=0xf7;
write_XDATA(0xf8, Pavalue);
return;
case 10:
Pavalue &=0xef;
write_XDATA(0xf8, Pavalue);
return;
case 11:
Pavalue &=0xdf;
write_XDATA(0xf8, Pavalue);
return;
case 12:
Pavalue &=0xbf;
write_XDATA(0xf8, Pavalue);
return;
case 13:
Pavalue &=0x7f;
write_XDATA(0xf8, Pavalue);
return;
case 14:
Pbvalue&=0xfe;
write_XDATA(0xf9, Pbvalue);
return;
default:
break;
}
}
else
{
switch(num)
{
case 0:
Led1=1;
return;
case 1:
Led2=1;
return;
case 2:
Led3=1;
return;
case 3:
Led4=1;
return;
case 4:
Led5=1;
return;
case 5:
Led6=1;
return;
case 6:
Pavalue |= 0x01;
write_XDATA(0xf8, Pavalue);
return;
case 7:
Pavalue |= 0x02;
write_XDATA(0xf8, Pavalue);
return;
case 8:
Pavalue |=0x04;
write_XDATA(0xf8, Pavalue);
return;
case 9:
Pavalue |=0x08;
write_XDATA(0xf8, Pavalue);
return;
case 10:
Pavalue |=0x10;
write_XDATA(0xf8, Pavalue);
return;
case 11:
Pavalue |=0x20;
write_XDATA(0xf8, Pavalue);
return;
case 12:
Pavalue |=0x40;
write_XDATA(0xf8, Pavalue);
return;
case 13:
Pavalue |=0x80;
write_XDATA(0xf8, Pavalue);
return;
case 14:
Pbvalue |=0x01;
write_XDATA(0xf9, Pbvalue);
return;
default:
break;
}
}
}
void Init8255(void) //初始化8255
{
write_XDATA(0xfb,0x80);
write_XDATA(0xf8,0x00);
write_XDATA(0xf9,0x00);//0xfe
write_XDATA(0xfa,0x00);//0xff
P1 &=0x03;
}
//键盘扫描程序
#define ESC 0x01
#define MOVE 0x02
#define DOWN 0x03
#define ENTER 0x04
#define UP 0x05
以上为键值定义
扫描函数如下:
UINT8 KeyScan(void)//键盘扫描
{
data UINT8 key_val;
data UINT8 current_key,k;
static data UINT8 flag=0;
key_val =P3;
key_val &=0x3b;
if(key_val==0x3b)
{
if(CloseFlag==0)
{
LCD_LED=LEDOFF;
}
return(0x00);
}
Delay1(500);
key_val =P3;
key_val &=0x3b;
k=0;
if(key_val==0x3b)
{
return(0x00);
}
while(1)
{
Delay1(400);
current_key=P3;
current_key &=0x3b;
k++;
ClearWatchDog();
if(current_key==0x3b)
{
flag=0;
break;
}
if(flag==0 && (k>250 && (current_key==0x33 || current_key==0x2b || current_key==0x1b)))
{
flag=1;
break;
}
if(flag==1 && (k>50 && (current_key==0x33 || current_key==0x2b || current_key==0x1b)))
break;
}
current_key =0x00;
if(key_val == 0x3a) current_key = ESC; //返回
else if(key_val == 0x39) current_key = ENTER; //开关
else if(key_val == 0x33) current_key = DOWN;//移动
else if(key_val == 0x2b) current_key = MOVE; //确认菜单
else if(key_val == 0x1b) current_key = UP;//修改
count2=0;
if(current_key!=0 && Voice==1)
{
Beep1(1);
}
if(current_key!=0 && CloseFlag==0)
{
//SingleCmd(DISPLAY_ON);
LCD_LED=LEDON;
CloseFlag=1;
changflag=1;
return(0x00);
}
return(current_key);
}
2. LCD工作原理:
Display control instruction
相关定义:
#define X_ADRESS 0xB8 /* Adress base for Page 0 */
#define Y_ADRESS 0x40 /* Adress base for Y0 */
#define START_LINE 0xC0 /* Adress base for line 0 */
#define DISPLAY_ON 0x3F /* Turn display on */
#define DISPLAY_OFF 0x3E /* Turn display off */
#define LCD_DATA P0
LCD相关函数:
void InitLcd(void) //LCD初始化
{
LCD_DATA = 0;
LCD_DI = 0;
LCD_RW = 0;
LCD_E = 0;
LCD_CS1 = 0;
LCD_CS2 = 0;
SingleCmd(DISPLAY_OFF); /* Display OFF */
SingleCmd(START_LINE);
SingleCmd(X_ADRESS);
SingleCmd(Y_ADRESS);
SingleCmd(DISPLAY_ON); /* Display ON */
}
/*送命令函数*/
void SingleCmd(UINT8 c)
{
LCD_E=0;
LCD_DI=0;
LCD_RW=1;
LCD_CS1=1;
LCD_CS2=1;
LcdWaitBusy (); /* wait until LCD not busy */
LCD_DI = 0; /* Instruction mode */
LCD_RW = 0; /* Write mode */
LCD_E = 1; /* Strobe */
Delay1(2);
LCD_DATA = c;/* outbyte */
Delay1(3);
LCD_E = 0;
Delay1(5);
LCD_CS1=0;
LCD_CS2=0;
}
/*送数据函数*/
void SingleData(UINT8 col,UINT8 c)
{
LCD_E=0;
LCD_DI=0;
LCD_RW=1;
if(col<64)
{
LCD_CS1=1;
}
else
{
LCD_CS2=1;
}
LcdWaitBusy(); /* wait until LCD not busy */
LCD_DI = 1; /* Data mode */
LCD_RW = 0; /* write mode */
LCD_DATA = c; /* outbyte */
Delay1(1);
LCD_E = 1; /* Strobe */
Delay1(2);
LCD_E = 0;
Delay1(3);
LCD_CS1=0;
LCD_CS2=0;
}
/*LCD BUSY 等待*/
void LcdWaitBusy (void)
{
LCD_DATA=0xFF; /* set LCD_DATA port in input mode */
LCD_DI = 0; /* Instruction mode */
LCD_RW = 1; /* Read mode */
LCD_E = 1; /* strobe */
Delay1(1);
LCD_E = 0;
while ( LCD_DATA & 0x7f == 0x80); /* mask the other status bits and test the BUSY bit */
}
/*清LCD显示*/
void clearRAM(UINT8 startp,UINT8 endp)
{
data UINT8 u8Page,u8Column;
for (u8Page = startp; u8Page < endp; u8Page++)
{
SetRAMAddr(u8Page,0x00);
for (u8Column = 0; u8Column < 128; u8Column++)
{
SingleData(u8Column,0x00); /* erase a column */
}
}
}
/*设置显示位置*/
void SetRAMAddr (UINT8 Page, UINT8 Col)
{
SingleCmd(X_ADRESS | Page); /* Set the page number */
SingleCmd(Y_ADRESS |Col);
}
有关LCD其它函数如显示LOGO画面、菜单和图形数据字形数据等可到网上下载。
//相关变量定义和函数说明
data UINT8 Year=0,Month=1,Date=1,Week=6,Hour=12,Minute=0,Second=0;
bit SecondFlag=0,MinuteFlag=0,HourFlag=0,DateFlag=0,MonthFlag=0,YearFlag=0;
data UINT8 Function=1,BackNum=1,CloseFlag=1;
data UINT8 Pic,Lang,Voice;
data UINT8 Pbvalue=0xff,Pcvalue=0xff,Pavalue=0xff;
data UINT16 count2=0;
sbit LCD_CS1 = P2^1;
sbit LCD_CS2 = P2^2;
sbit LCD_RW = P2^4;
sbit LCD_DI = P2^5;
sbit LCD_E = P2^3;
sbit key_out0 = P1^5;
sbit MUNIC = P1^1;
void InitLcd(void);
void Delay1(UINT16 time);
void LOGO(void);
void Date_display(UINT8 w,UINT8 y,UINT8 m,UINT8 d,UINT8 n);
void Time_display(UINT8 row,UINT8 h,UINT8 m,UINT8 s,UINT8 n);
void clearRAM(unsigned char startpage,unsigned char stoppage);
void SetRAMAddr(UINT8 Page, UINT8 Col);
void Msingle_font_pattern(unsigned char *page_num, unsigned char page_y_in, unsigned char col_x_in,bit flag);
void HzDisplay(unsigned char *page_num, unsigned char page_y_in, unsigned char col_x_in,bit flag);
void Display_Line(unsigned char num, unsigned char page_y_in, unsigned char len,bit flag);
void Second_moudel(void);
void Display_Save(UINT8 row,UINT8 col);
void Timer0_Init(void);
void CPUInitial(void);
void Num_Display(UINT8 num, unsigned char page_y_in, unsigned char col_x_in,bit flag);
void SingleCmd(unsigned char c);
void SingleData(UINT8 col,unsigned char c);
void LcdWaitBusy(void);
void Contral8255(UINT8 num,bit flag);
void Beep1(UINT8 num);
void LedContral(UINT8 num,bit flag);
UINT8 KeyScan(void);
sbit ISDA=P2^6;
sbit ISCL=P2^7;
sbit SPEAKER=P1^1;
sbit Led1=P1^2;
sbit Led2=P1^3;
sbit Led3=P1^4;
sbit Led4=P1^5;
sbit Led5=P1^6;
sbit Led6=P1^7;
bit EEPROMByteWrite0(UINT16 addr,UINT8 value);
UINT8 EEPROMByteRead0(UINT16 addr1);
void I2cSentByte();
void I2cStart(void);
void I2cStop(void);
extern void _nop_ (void);
data UINT8 c,BeepFlag=0;
bit ack;
bit Contralflag=0;
data UINT8 Luopencloseflag[15];
data UINT8 count1;
bit changflag=1;
3. 24C512简介:
它与其它24CXX系列一样,是一种I2C总线的存储器,64K*8的容量。原理在综合模块已讲解,下面给出相应的C程序。
/*24c512 读写函数*/
bit EEPROMByteWrite0(UINT16 addr,UINT8 value)
{
I2cStart();
c=0xa0;
I2cSentByte();
if (ack==0)
return(0);
c=addr>>8;
I2cSentByte();
if (ack==0)
return(0);
c=addr;
I2cSentByte();
if (ack==0)
return(0);
c=value;
I2cSentByte();
if (ack==0)
return(0);
I2cStop();
Delay1(50);
return(1);
}
UINT8 EEPROMByteRead0(UINT16 addr1)
{
UINT8 bytedata,j;
I2cStart();
c=0xa0;
I2cSentByte();
if (ack==0)
return(0);
c=addr1>>8;
I2cSentByte();
if (ack==0)
return(0);
c=addr1;
I2cSentByte();
if (ack==0)
return(0);
I2cStart();
c=0xa1;
I2cSentByte();
if (ack==0)
return(0);
ISDA=1;
for (j=0;j<8;j++)
{
_nop_();
ISCL=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
ISCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
bytedata<<=1;
if (ISDA)
bytedata|=0x01;
_nop_();
_nop_();
}
ISCL=0;
_nop_();
_nop_();
_nop_();
_nop_();
ISCL=1;
I2cStop();
return (bytedata);
}
void I2cStart(void)
{
ISDA=1;
ISCL=1;
_nop_();
_nop_();
_nop_();
ISDA=0;
_nop_();
_nop_();
_nop_();
ISCL=0;
_nop_();
_nop_();
}
void I2cStop(void)
{
ISDA=0;
ISCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
ISDA=1;
_nop_();
_nop_();
_nop_();
_nop_();
ISCL=0;
}
void I2cSentByte()
{
data UINT8 temp1,temp2;
for(temp1=0;temp1<8;temp1++)
{
temp2=c &0x80;
if(temp2==0x80)
ISDA=1;
else
ISDA=0;
c<<=1;
_nop_();
_nop_();
_nop_();
_nop_();
ISCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
ISCL=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
_nop_();
_nop_();
ISDA=1;
_nop_();
_nop_();
_nop_();
_nop_();
ISCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
if(ISDA==1)
ack=0;
else
ack=1;
ISCL=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
/*CPU 初始化、定时器初始化、定时器中断函数*/
/************************************************************************/
/* System Register of CPU Initialize */
/**************************************************************************/
void CPUInitial(void)//CPU初始化
{
IE = 0x80;
IP = 0x01;
P0 = 0xff;
P1 = 0xFF;
P2 = 0xff;
P3 = 0xff;
}
void Timer0_Init(void)//时钟0初始化
{
TMOD=0x01;
TCON = 0x00;
TL0 = 0xe0;
TH0 = 0x3c;
TR0 = 1 ;
}
void Delay1(UINT16 time) //延时函数
{
UINT16 i;
for(i=0;i