#include <avr/io.h> #include <avr/delay.h>
/* ********************************************************************************************************* * PORTA TYPES * (Compiler Specific) ********************************************************************************************************* */
//typedef bit BOOLEAN; typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ typedef signed char INT8S; /* Signed 8 bit quantity */ typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ typedef signed int INT16S; /* Signed 16 bit quantity */ typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ typedef signed long INT32S; /* Signed 32 bit quantity */ typedef float FP32; /* Single precision floating point */ typedef double FP64; /* Double precision floating point */
#define DI 0 /* H : PORTA singal, L : Instruction singal */ #define CS 1 /* 液晶显模块(LCM)的片选端 */ #define RD 2 /* L : 当芯片选中,此引脚为低电平时,数据开始读 */ #define WR 3 /* L : 当芯片选中,此引脚为低电平时,数据开始写 */ #define RES 4 /* L : 当芯片选中,此引脚为低电平时,LCM初始化 */ #define SetBit(sfr,bit) (sfr|=(1<<bit)) #define ClsBit(sfr,bit) (sfr&=~(1<<bit)) /*$PAGE*/
/* ********************************************************************************************************* * FUNCTION PROTOTYPES ********************************************************************************************************* */ void WriteCMD (INT8U cmd); void WriteDat (INT8U dat); INT8U ReadStatus (void); void InitLCM (void); void ClearLCM (void); void DisHZ (INT8U page, INT8U col, INT8U isnh, INT8U isnl); void DisChar (INT8U page, INT8U col, INT8U order); void DisString (INT8U x, INT8U y, INT8U *pst); /*$PAGE*/
/* ASCII字库代码 8x16点阵 */
INT8U ASCII[16*96] = {}; void InitLCM (void) { ClsBit(PORTB, RES); /* 硬复位 */ _delay_us (500); SetBit(PORTB, RES); WriteCMD (0xe2); /* 软件复位 ` */ _delay_us (10); WriteCMD (0xa2); /* LCD BIAS=1/9 */ WriteCMD (0xa0); /* 列地址移动方向:ADC=0(SEG1->SEG132) */ WriteCMD (0xc8); /* 行扫描方向:SHL=1(COM64->COM1) */ _delay_us (10); WriteCMD (0x2f); /* 电源控制模式:VC,VR,VF=111 */ _delay_us (10); WriteCMD (0x26); /* 内部调整电阻比率:R2,R1,R0=111 */ _delay_us (10); WriteCMD (0x81); /* 对比度寄存器模式 */ WriteCMD (0x3f); /* 对比度寄存器值 修改这个值就可以调节对比度了 */ WriteCMD (0x40); /* 起始行 */ WriteCMD (0xe0); /* 写入数据时列地址自动加1,但读时不变 */ WriteCMD (0xaf); /* 开显示 */ } /*$PAGE*/
/* ********************************************************************************************************* * 送入液晶显示模块LCM数据或指令 void WriteCMD (INT8U cmd) { while(ReadStatus()&0x80); DDRA = 0xff; ClsBit(PORTB, DI); /* 数据/指令控制 */ PORTA = cmd; /* 送入指令/数据 */ ClsBit(PORTB, CS); /* LCM片选 */ ClsBit(PORTB, WR); /* 写操作 */ SetBit(PORTB, RD); /* 确保不被读操作 */ asm("nop"); asm("nop"); SetBit(PORTB, WR); SetBit(PORTB, CS); } /*$PAGE*/
void WriteDat (INT8U dat) { while(ReadStatus()&0x80); DDRA = 0xff; SetBit(PORTB, DI); /* 数据 */ PORTA = dat; /* 送入数据 */ ClsBit(PORTB, CS); /* LCM片选 */ ClsBit(PORTB, WR); /* 写操作 */ SetBit(PORTB, RD); /* 确保不被读操作 */ asm("nop"); asm("nop"); SetBit(PORTB, WR); SetBit(PORTB, CS); } /*$PAGE*/
INT8U ReadStatus (void) { INT8U status; PORTA = 0xff; DDRA = 0x00; ClsBit(PORTB, DI); ClsBit(PORTB, CS); SetBit(PORTB, WR); ClsBit(PORTB, RD); asm("nop"); asm("nop"); status = PINA; SetBit(PORTB, RD); DDRA = 0xff; SetBit(PORTB, CS); return (status); } /*$PAGE*/
/* ********************************************************************************************************* * 清屏 * * Description: 这个函数用将液晶显示所有信息清除 * * Arguments : none * * Returns : none ********************************************************************************************************* */ void ClearLCM (void) { INT8U i, j; WriteCMD (0x40); //Set Display Start Line = com0 for (i=0; i<8; i++) { WriteCMD (0xb0 | i); //Set Page Address WriteCMD (0x10); //Set Column Address = 0 WriteCMD (0x01); //Colum from 1 -> 129 auto add for(j=0; j<128; j++) WriteDat (0x00); } } /*$PAGE*/
/* ********************************************************************************************************* * 液晶显示模块显示汉字 * * Description: 这个函数用于向液晶显示模块送入显示的汉字. 汉字通常用16X16的点阵表示, 所以显示汉字就要求: * 当显示0~7行(0~15列)时, 用第一页. 当显示第8~15行(0~15列)时, 用第二页. * * Arguments : pgae 行号 * col 列号 * ch1 * * Returns : none ********************************************************************************************************* */ void DisHZ (INT8U page, INT8U col, INT8U isnh, INT8U isnl) { INT32U addr; INT8U i, hzPORTA[32]; INT16U ISN = 0; ISN = (INT16U)isnh<<8 | (INT16U)isnl; /* 将汉字内码的第一字节第二字节合成一个字 */ addr = 0x00004000 + ISN; /* 汉字点阵码在外接Flash中存储的首地址 */ //spiFlash(addr, hzPORTA, 32); /* 读出32个汉字点阵数据 */ WriteCMD ((page&0x07) | 0xb0); /* 页地址指令配置 */ WriteCMD ((col>>4) | 0x10 ); /* 列地址的高4位 */ WriteCMD (col & 0x0F); /* 列地址的低4位 */ for (i=0; i<16; i++) /* 显示上半个汉字 */ WriteDat (hzPORTA); page++; WriteCMD ((page&0x07) | 0xb0); /* 页地址指令配置 */ WriteCMD ((col>>4) | 0x10 ); /* 列地址的高4位 */ WriteCMD (col & 0x0F); /* 列地址的低4位 */ for (; i<32; i++) /* 显示下半个汉字 */ WriteDat (hzPORTA); } /*$PAGE*/
/* ********************************************************************************************************* * 显示ASICC字符的函数 * * Description: 这个函数用于向液晶显示模块送入显示的汉字. 汉字通常用16X16的点阵表示, 所以显示汉字就要求: * 当显示0~7行(0~15列)时, 用第一页. 当显示第8~15行(0~15列)时, 用第二页. * * Arguments : page 页地址(行号) * col 列地址 * order 字符数据地址指针 * * Returns : none ********************************************************************************************************* */ void DisChar (INT8U page, INT8U col, INT8U order) { INT8U i; INT16U x; x = order - 0x20; x *= 0x10; //ASICC字符从0x20开始,每个16 byte WriteCMD ((page&0x07) | 0xB0); //Set Page Address WriteCMD ((col>>4) | 0x10); //Set Column Address High Byte WriteCMD (col & 0x0F ); //Low Byte Colum from 1 -> 129 auto add for(i=0;i<8;i++) { WriteDat (ASCII[x]); x++; } page++; //下半字符page+1 WriteCMD ((page&0x07) | 0xB0); //Set Page Address WriteCMD ((col>>4) | 0x10); //Set Column Address High Byte WriteCMD (col & 0x0F ); //Low Byte Colum from 1 -> 129 auto add for (i=0; i<8; i++) { WriteDat (ASCII[x]); x++; } page--; //写完一个字符page还原 }
/*$PAGE*/ /* ********************************************************************************************************* * 显示字符串函数 * * Description: 这个函数用于向液晶显示模块送入显示的汉字. 汉字通常用16X16的点阵表示, 所以显示汉字就要求: * 当显示0~7行(0~15列)时, 用第一页. 当显示第8~15行(0~15列)时, 用第二页. * * Arguments : x 列位置(即偏移第0列的值, 值只能取0~15, 即一个字符所占的列为8, 能显示16列) * y 行位置(只能取0~7) * pst 指向要显示的字体位置 * * Returns : none ********************************************************************************************************* */ void DisString (INT8U x, INT8U y, INT8U *pst) { INT8U col, page; col = y * 8; page = 0xb0 | x; while ( *pst != '\0' ) { if ( *pst < 0x80 ) //小于0x80是字符 { DisChar(page, col, *pst); //显示ASC字符 col += 2*8; if (col > 15*8) { col = 0; page += 2; } pst++; //下一个要显示的字符 } else //大于0x80是汉字 { if (col >= 15*8) { DisChar (page, col, 0x20); //一行的尾部只有半个汉字位置的处理,加一个空格,在下一行开始显示 col = 0; page += 2; if (page > 7) page = 0; } DisHZ (page, col, *pst, *(pst+1)); //显示一个汉字 col += 2*8; pst += 2; if (col > 15*8) { col = 0; page += 2; } } if (page > 7) { page = 0; col = 0; } } } /*$PAGE*/
INT16S main(void) { PORTA=0x00; DDRA=0xFF;
PORTB=0x00; DDRB=0xFF;
PORTC=0x00; DDRC=0xFF;
PORTD=0x00; DDRD=0x0B;
TCCR0=0x00; TCNT0=0x00; OCR0=0x00;
TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00;
ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00;
GICR|=0x40; MCUCR=0x00; MCUCSR=0x00; GIFR=0x40;
TIMSK=0x00;
UCSRA=0x00; UCSRB=0x18; UCSRC=0x86; UBRRH=0x00; UBRRL=0x2F;
ACSR=0x80; SFIOR=0x00;
SPCR=0x40; SPSR=0x00;
TWSR=0x00; TWBR=0x02; TWAR=0x00; TWCR=0x04;
asm("sei"); InitLCM (); ClearLCM (); while (1) { DisString(0, 2, "you are pig!"); }; return (0); }
|