第一次用到LCD12864滚屏功能- #include <iom16v.h>
- #include <macros.h>
- #include <stdio.h>
- #define LCDb_CTRL PORTD //12864控制端口定义
- #define LCDb_CTRL_DDR DDRD //控制端口方向寄存器定义
- #define LCDb_RS PD4 //定义四个控制引脚
- #define LCDb_RW PD5
- #define LCDb_E PD6
- #define LCDb_RST PD7
- #define LCDb_SET_RS LCDb_CTRL|=BIT(LCDb_RS) //写数据
- #define LCDb_SET_RW LCDb_CTRL|=BIT(LCDb_RW) //读操作
- #define LCDb_SET_E LCDb_CTRL|=BIT(LCDb_E) //使能信号
- #define LCDb_SET_RST LCDb_CTRL|=BIT(LCDb_RST) //不是能复位
- #define LCDb_CLR_RS LCDb_CTRL&=~BIT(LCDb_RS) //写指令
- #define LCDb_CLR_RW LCDb_CTRL&=~BIT(LCDb_RW) //写操作
- #define LCDb_CLR_E LCDb_CTRL&=~BIT(LCDb_E) //失能信号
- #define LCDb_CLR_RST LCDb_CTRL&=~BIT(LCDb_RST) //使能复位
- //#define roll_number 13 所显示文字的行数
- unsigned char *string[]={
- "----南怀瑾------",
- "佛为心, ",//空白位空格键,两空格一个汉字空间
- "道为骨, ",
- "儒为表, ",
- "大度看世界。 ",
- "技在手, ",
- "能在身, ",
- "思在脑, ",
- "从容过生活。 ",
- "三千年读史, ",
- "不外功名利禄。 ",
- "九**悟道, ",
- "终归诗酒田园。 "
- };
- void Delayus(unsigned int US)
- {
- unsigned int i;
- US=US*5/4; //5/4是在8MHz晶振下,通过软件仿真反复实验得到的数值
- for( i=0;i<US;i++);
- }
- void Delayms(unsigned int MS)
- {
- unsigned int i,j;
- for( i=0;i<MS;i++)
- for(j=0;j<1141;j++); //1141是在8MHz晶振下,通过软件仿真反复实验得到的数值
- }
- void Board_init(void)
- {
- DDRA=0xFF; //将四个IO口全部配置为输出
- DDRB=0xFF;
- DDRC=0xFF;
- DDRD=0xFF;
- SPCR=0x00; //还原SPI口,使其为正常端口
- PORTA|=BIT(PA6);//(BEEP)关闭蜂鸣器
- PORTC&=~BIT(PC6); //(RELAY)初始化继电器为常闭连接状态
- PORTA&=~BIT(PA1); //关闭SPI总线DA
-
- PORTB=0xFF; //关闭LED
- PORTA|=BIT(2); //锁存数据,使LED熄灭
- Delayus(5);
- PORTA&=~BIT(2);
- PORTB=0x00; //输出段选
- PORTA|=BIT(3);
- Delayus(50);
- PORTA&=~BIT(3);
- PORTB=0xFF; //输出位选
- PORTA|=BIT(4);
- Delayus(50);
- PORTA&=~BIT(4);
-
- PORTD=0xFF;
- PORTA|=BIT(PA7);
- Delayus(50);
- PORTA&=~BIT(PA7);
- }
- unsigned char Read_cmd(void)
- {
- unsigned char Rcmd,RD=0;
- LCDb_CLR_RS;
- LCDb_SET_RW; //RS-->L,RW-->H 读出忙标志位(BF)以及位址计数器(AC)的状态
- LCDb_SET_E;
- DDRB=0x00;
- Delayms(1);
- Rcmd=PINB;
- LCDb_CLR_E;
- DDRB|=0xff;
- if(Rcmd&0x80)
- RD=1; //忙
- else
- RD=0;
-
- return RD;
- }
- void Write_cmd(unsigned char iCmd)
- {
- while(Read_cmd());
- LCDb_CLR_RS;
- LCDb_CLR_RW; //RS-->L,RW-->L MCU写指令到指令暂存器
- LCDb_SET_E;
- PORTB=iCmd;
- Delayus(100);
- LCDb_CLR_E;
- }
- void Write_dat(unsigned char iDat)
- {
- while(Read_cmd());
- LCDb_SET_RS; //RS-->H,RW-->L MCU写数据到资料暂存器(DR)
- LCDb_CLR_RW;
- LCDb_SET_E;
- PORTB=iDat;
- Delayus(100);
- LCDb_CLR_E;
- }
- void LCD12864_portini(void)
- {
- LCDb_CTRL_DDR |= BIT(LCDb_RS)|BIT(LCDb_RW)|BIT(LCDb_E)|BIT(LCDb_RST);//配置控制管脚为输出
- DDRB |= 0xFF; //配置数据管脚为输出
- LCDb_SET_RST; //不使能复位端
- //并口设置在硬件上实现
- }
- //void main(void)
- void roll_display(unsigned char roll_number)//所显示文字的行数#define roll_number 13
- {
- unsigned char i,j,row,roll_flag=0;
- unsigned char row_addr=0x80,flag=0;
-
- Board_init();
- LCD12864_portini();
- Delayms(500);
- /*
- 显示前的初始化命令
- */
- Write_cmd(0x38);//功能、模式设定
- Write_cmd(0x0c);//打开显示
- Write_cmd(0x01);//清屏
- Write_cmd(0x06);//输入模式设定
- Delayms(500);
- for(i=0;i<2;i++)
- {
- row_addr=row_addr+i*0x10;
- if(i%2==0)
- {
- Write_cmd(row_addr); //0x80
- for(j=0;*(string[flag]+j)!='\0';j++) //*(string[0]+j)
- Write_dat(*(string[flag]+j)); //写入"----南怀瑾------"
- flag++; //flag-->1
- Write_cmd(row_addr+0x10); //0x90
- for(j=0;*(string[flag]+j)!='\0';j++) //*(string[1]+j)
- Write_dat(*(string[flag]+j)); //写下"佛为心, "
- flag++; //flag-->2
- }
- else
- {
- Write_cmd(row_addr-0x08); //0x88
- for(j=0;*(string[flag]+j)!='\0';j++) //*(string[2]+j)
- Write_dat(*(string[flag]+j)); //写下"道为骨, ",
- flag++; //flag-->3
- Write_cmd(row_addr+0x08); //0x98
- for(j=0;*(string[flag]+j)!='\0';j++) //*(string[3]+j)
- Write_dat(*(string[flag]+j)); //写下"儒为表, "
- flag++; //flag-->4
- }
- }
- row_addr=0xa0;
- Write_cmd(row_addr); //0xa0
- for(j=0;*(string[flag-2]+j)!='\0';j++) //*(string[2]+j)
- Write_dat(*(string[flag-2]+j)); //写下"道为骨, ",
- Write_cmd(row_addr+0x08); //0xa8
- for(j=0;*(string[flag]+j)!='\0';j++) //*(string[4]+j)
- Write_dat(*(string[flag]+j)); //写下"大度看世界。 ",
- flag++; //flag-->5
- Write_cmd(0x0c); //写入开显示命令
- row=4;
- while(1)
- {
- if(roll_flag>=64)
- roll_flag=0;
- switch(row)
- {
- case 1:row_addr=0x80;break;
- case 2:row_addr=0x90;break;
- case 3:row_addr=0xa0;break;
- case 4:row_addr=0xb0;break;
- }
- switch(row)
- {
- case 1:row=2;break;
- case 2:row=3;break;
- case 3:row=4;break;
- case 4:row=1;break;
- }
- if(flag==1)
- flag=(roll_number+1);
- for(i=0;i<8;i++)
- {
- Write_cmd(0x34);//功能设定,进入扩充指令
- Write_cmd(0x03);//允许输入卷动地址
- Write_cmd(0x40+roll_flag++);//输入卷动地址rollflag
- Write_cmd(0x30);//功能设定,进入基本指令
- Write_cmd(row_addr+i);//数据写入的地址
- if((*(string[flag-2]+2*i)!='\0')&&((flag-2)>=0)) //*(string[3]...)
- Write_dat(*(string[flag-2]+2*i)); //一个汉字的低字节
- if((*(string[flag-2]+2*i+1)!='\0')&&((flag-2)>=0))
- Write_dat(*(string[flag-2]+2*i+1)); //一个汉字的高字节
- Delayms(150);
- }
- if(flag>=roll_number+1)
- flag=1;
- if(flag>=roll_number)
- flag=0;
- for(i=0;i<8;i++)
- {
- Write_cmd(0x34);//扩充指令
- Write_cmd(0x03);//允许输入卷动地址
- Write_cmd(0x40+roll_flag++);//输入卷动地址
- Write_cmd(0x30);//进入基本指令
- Write_cmd(row_addr+i+8);//数据写入的地址
- if(*(string[flag]+2*i)!='\0') //*(string[5]...)
- Write_dat(*(string[flag]+2*i));
- if(*(string[flag]+2*i+1)!='\0')
- Write_dat(*(string[flag]+2*i+1));
- Delayms(150);
- }
- flag++;
- }
- }
,网上查找资料,最后调试通过,故封装成一个模块,在此分享,同时求教不同的实现方式。LCD使用的是ST7920版,本次实现汉字滚屏,英文要修改部分参数。
|