📄 lcd-8bit.c
字号:
/*
本程序用于图形点阵(含汉字字库)lcd 8BIT控制
使用方法:
#asm
.equ __lcd_data_port=0x18 ;PORTA
.equ __lcd_con_port=0x28 ;PORTB
.equ __lcdcs=3
.equ __lcdrs=4
.equ __lcdwr=5
.equ __lcdrd=6
.equ __lcdrst=7
#endasm
#include <LCD-8BIT.h>
*/
#asm
.equ __lcd_data_direction=__lcd_data_port-1
.equ __lcd_data_pin=__lcd_data_port-2
.equ __lcd_con_direction=__lcd_con_port-2
.equ __lcd_con_pin=__lcd_con_port-2
.equ __lcd_cs=__lcdcs
.equ __lcd_rs=__lcdrs
.equ __lcd_wr=__lcdwr
.equ __lcd_rd=__lcdrd
.equ __lcd_rst=__lcdrst
#endasm
#include <stdio.h>
#pragma used+
static unsigned int _lcd_xmax,_lcd_ymax;
#pragma used-
// 延时-----------------------------------------------
void _lcd_delay(void)
{
#asm
nop
nop
#endasm
}
void _lcd_out_data(unsigned char data)
{
#asm
ld r26,y
out __lcd_data_port,r26
#endasm
_lcd_delay();
#asm
//写使能
cbi __lcd_con_port,__lcd_wr
#endasm
_lcd_delay();
#asm
//写完成
sbi __lcd_con_port,__lcd_wr
#endasm
_lcd_delay();
}
// 发送命令 --------------------------------------------------
void lcd_cmd(unsigned char reg,signed char com)
{
#asm
//配置引脚为输出
ldi r26,0xff
out __lcd_data_direction,r26
sbi __lcd_con_direction,__lcd_cs
sbi __lcd_con_direction,__lcd_rs
sbi __lcd_con_direction,__lcd_wr
sbi __lcd_con_direction,__lcd_rd
sbi __lcd_con_direction,__lcd_rst
#endasm
#asm
//设置状态
cbi __lcd_con_port,__lcd_rs
sbi __lcd_con_port,__lcd_rd
sbi __lcd_con_port,__lcd_wr
#endasm
#asm
//片选
cbi __lcd_con_port,__lcd_cs
#endasm
_lcd_delay();
_lcd_out_data(reg);
_lcd_out_data(com);
#asm
//取消片选
sbi __lcd_con_port,__lcd_cs
#endasm
}
// 发送数据
void lcd_data(unsigned char data)
{
#asm
//配置引脚
ldi r26,0xff
out __lcd_data_direction,r26
sbi __lcd_con_direction,__lcd_cs
sbi __lcd_con_direction,__lcd_rs
sbi __lcd_con_direction,__lcd_wr
sbi __lcd_con_direction,__lcd_rd
sbi __lcd_con_direction,__lcd_rst
#endasm
#asm
//设置状态
sbi __lcd_con_port,__lcd_rs
sbi __lcd_con_port,__lcd_rd
sbi __lcd_con_port,__lcd_wr
#endasm
#asm
//片选
cbi __lcd_con_port,__lcd_cs
#endasm
_lcd_delay();
_lcd_out_data(data);
#asm
//取消片选
sbi __lcd_con_port,__lcd_cs
#endasm
}
static unsigned char _lcd_read_data0(void)
{
#asm
cbi __lcd_con_port,__lcd_rd
#endasm
_lcd_delay();
#asm
in r30,__lcd_data_pin
sbi __lcd_con_port,__lcd_rd
#endasm
_lcd_delay();
}
// 读数据
static unsigned char lcd_read_data()
{
#asm
//配置引脚
ldi r26,0x00
out __lcd_data_direction,r26
sbi __lcd_con_direction,__lcd_cs
sbi __lcd_con_direction,__lcd_rs
sbi __lcd_con_direction,__lcd_wr
sbi __lcd_con_direction,__lcd_rd
sbi __lcd_con_direction,__lcd_rst
#endasm
#asm
//片选
cbi __lcd_con_port,__lcd_cs
#endasm
#asm
//设置状态
sbi __lcd_con_port,__lcd_rs
sbi __lcd_con_port,__lcd_rd
sbi __lcd_con_port,__lcd_wr
#endasm
_lcd_delay();
#asm
cbi __lcd_con_port,__lcd_rd
#endasm
_lcd_delay();
#asm
in r30,__lcd_data_pin
sbi __lcd_con_port,__lcd_rd
sbi __lcd_con_port,__lcd_cs
#endasm
}
// 读寄存器
unsigned char lcd_read_com(unsigned char comreg)
{
//写入地址
unsigned char cmd;
#asm
//配置引脚
ldi r26,0xff
out __lcd_data_direction,r26
sbi __lcd_con_direction,__lcd_cs
sbi __lcd_con_direction,__lcd_rs
sbi __lcd_con_direction,__lcd_wr
sbi __lcd_con_direction,__lcd_rd
sbi __lcd_con_direction,__lcd_rst
#endasm
#asm
//设置状态
cbi __lcd_con_port,__lcd_rs
sbi __lcd_con_port,__lcd_rd
sbi __lcd_con_port,__lcd_wr
#endasm
#asm
//片选
cbi __lcd_con_port,__lcd_cs
#endasm
_lcd_delay();
_lcd_out_data(comreg);
#asm
//配置引脚为输出
ldi r26,0x00
out __lcd_data_direction,r26
#endasm
#asm
//设置状态
cbi __lcd_con_port,__lcd_rs
sbi __lcd_con_port,__lcd_rd
sbi __lcd_con_port,__lcd_wr
#endasm
cmd=_lcd_read_data0();
#asm
//取消片选
sbi __lcd_con_port,__lcd_cs
#endasm
return cmd;
}
//移到坐标
void lcd_gotoxy(unsigned char x,unsigned char y)
{
lcd_cmd(0x60,x);
lcd_cmd(0x70,y);
}
// 发送显示SRAM中的数据
void lcd_puts(unsigned char *str)
{
do
{
lcd_data(*str);
str++;
}
while(*str!=0);
}
// 发送显示flash中的数据
void lcd_putsf(unsigned char flash *str)
{
do
{
lcd_data(*str);
str++;
}
while(*str!=0);
}
// 整屏的写入数据
void lcd_fullscreenfill(unsigned char fill_data)
{
unsigned char i,j;
lcd_gotoxy(0,0);
for(i=0;i<_lcd_ymax;i++)
{
for(j=0;j<(_lcd_xmax>>3);j++)
{
lcd_data(fill_data);
}
}
}
// 显示字符C
void lcd_putchar(unsigned char c)
{
lcd_data(c);
}
// 初始化
void lcd_init(unsigned int x,unsigned int y)
{
unsigned char val=0;
unsigned char awrr,awbr,dwrr,dwbr;
#asm
//配置引脚为输出
ldi r26,0xff
out __lcd_data_direction,r26
sbi __lcd_con_direction,__lcd_cs
sbi __lcd_con_direction,__lcd_rs
sbi __lcd_con_direction,__lcd_wr
sbi __lcd_con_direction,__lcd_rd
sbi __lcd_con_direction,__lcd_rst
#endasm
#asm
//初始状态
sbi __lcd_con_port,__lcd_rd
sbi __lcd_con_port,__lcd_wr
sbi __lcd_con_port,__lcd_rs
sbi __lcd_con_port,__lcd_rst
#endasm
#asm
//片选
cbi __lcd_con_port,__lcd_cs
#endasm
delay_ms(200);
// 复位电平
#asm
cbi __lcd_con_port,__lcd_rst
#endasm
delay_ms(600);
#asm
sbi __lcd_con_port,__lcd_rst
#endasm
delay_ms(200);
_lcd_xmax=x;
_lcd_ymax=y;
// 工作视察参数的设定
if( (x==160) & (y==80) ){awrr=0x13;awbr=0x4f;dwrr=0x13;dwbr=0x4f;}
if( (x==160) & (y==128) ){awrr=0x13;awbr=0x7f;dwrr=0x13;dwbr=0x80;}
if( (x==160) & (y==160) ){awrr=0x13;awbr=0x9f;dwrr=0x13;dwbr=0x9f;}
if( (x==240) & (y==64) ){awrr=0x1d;awbr=0x3f;dwrr=0x1d;dwbr=0x3f;}
if( (x==240) & (y==128) ){awrr=0x1d;awbr=0x7f;dwrr=0x1d;dwbr=0x80;}
if( (x==240) & (y==160) ){awrr=0x1d;awbr=0x9f;dwrr=0x1d;dwbr=0x9f;}
if( (x==320) & (y==240) ){awrr=0x27;awbr=0xef;dwrr=0x27;dwbr=0xef;}
// 工作窗口设定
lcd_cmd(0x20,awrr);
lcd_cmd(0x30,dwbr);
lcd_cmd(0x40,0x00);
lcd_cmd(0x50,0x00);
// 显示窗口设定
lcd_cmd(0x21,awrr);
lcd_cmd(0x31,dwbr);
lcd_cmd(0x41,0x00);
lcd_cmd(0x51,0x00);
// CPXR X方向光标寄存器
lcd_cmd(0x60,0x00);
// CPYR Y方向光标寄存器
lcd_cmd(0x70,0x00);
/*************************************************************************************
WLCR 控制寄存器
7/6 电源模式 11-正常,00-关闭
5 软件复位 1-重置所有缓存器, 0-正常
4 保留
3 显示模式 1-文本 0-图形
2 显示开关 1-开 0-关
1 闪烁控制 1-整屏闪烁 0-正常
0 负向显示 1-正常 0-负向显示
*************************************************************************************/
val=0;
val= (0b11<<6) | (0<<5) | (0<<4) | (1<<3) | (1<<2) | (0<<1)| 1;
lcd_cmd(0x00,val);
/*************************************************************************************
MISC 时钟控制
7 保留
6 时钟输出控制 1-允许 0-禁止
5 保留
4 中断/忙标志的触发位设定 1-高电平 0-低电平
3-2 保留
1-0 系统时钟选择 00-3MHz 01-4MHz 10-8MHz 11-12MHz
*************************************************************************************/
val=0;
val= (0<<6) | (0<<4) | 0b10;
lcd_cmd(0x01,val);
/*************************************************************************************
WCCR 光标控制寄存器,直接给DDDRAM发送数据,地址自动+1,光标宽度为自动
7 读DDRM时光标是否自动移位 1-Y 0-N
6 中/英文文字对齐 1-Y 0-N
5 正反相存储数据 1-正相 0-反相
4 粗体设置 1-粗体 0-正常
3 写DDRM时光标是否自动移位 1-Y 0-N
2 光标是否显示 `1-Y 0-N
1 光标是否闪烁 1-Y 0-N
0 光标宽度模式 1-自动调整 0-固定8Pixel
*************************************************************************************/
val=0;
val= (0<<7) | (0<<6) | (1<<5) | (0<<4) | (1<<3) | (0<<2) | (0<<1)| 1;
lcd_cmd(0x10,val);
/*************************************************************************************
DWLR 光标大小控制寄存器
7-4 设定光标高度
3-0 设定行与行的距离
*************************************************************************************/
val=0;
val = (2<<4) | 0;
lcd_cmd(0x11,val);
/*************************************************************************************
MAMR
7 图形模式时,光标自动移位方向 1-先水平 0-先垂直
6-4 图层显示模式 000-灰阶,001-显示Page1 010-显示Page2 011-同时显示Page1和Page2
3-2 双层显示时图层逻辑关系 00-OR 01-XOR 10-NOR 11-AND
1-0 设定读写图层 00-存取Page0 01-存取Page0 10-存取Page1 11-存取Page0/1
*************************************************************************************/
val=0;
val = (0<<7) | (0b001<<4) | (0b00<<2) | 0b01;
lcd_cmd(0x12,val);
/*******************************************************
// BTMR 闪烁时间寄存器
闪烁时间=[80H] * (1/Frame_Rate)
Frame_Rate 的高定是通常依照LCD面板所提供的最佳值
*****************************************************/
lcd_cmd(0x80,0x2e);
/***********************************************************************
// SCCR 工作时钟
SCCR = (SCLK * DW) / (Seg * Com * FRM)
SCLK RA8803系统频率 单位:Hz
DW 驱动器的数据总线宽度 单位:Bit
Seg 面板的Seg大小 单位:Pixel
Com 面板的Com大小 单位:Pixel
FRM 面板的Frame Rate大小 单位:Hz
限制:
DW=0 DW=4时,SCCR>=4
DW=1 DW=8时,SCCR>=2
*****************************************************/
lcd_cmd(0x90,0x04);
// INTR
lcd_cmd(0xa0,0x00);
/********************************************************
// PNTR 数据模式寄存器
当F0H中的bit3为'1',将自动读取本缓存器E0H的数据,然后全部填写到DDRAM内,
之后F0H中的bit3被清除为'0'
在灰阶模式下 bit[6-4]=000,用来控制灰阶显示效果
*****************************************************/
lcd_cmd(0xe0,0x00);
/********************************************************
FNCR 字体控制寄存器
7 字型ROM转换 1-使能 0-禁止
6 字型ROM的地址空间选择 1-下部256KB 0-上部256KB
5-4 字型ROM的选择 00-简体256K 01-繁体256K 10-简体512K
3 填写PNTR的数据到DDRAM 1-开始写入 0-未动作
2 强制为ASCII解码 1-是 0-否
1-0 ASCII区块选择 00-区块0 01-区块1 10-区块2 11-区块3
*****************************************************/
val=0;
val = (1<<7) | (0<<6) | (0b10<<4) | (0<<3) | (0<<2) | 0b00;
lcd_cmd(0xf0,val);
/********************************************************
FVHT 字体大小
7-6 水平方向的大小 00-1倍 00-2倍 00-3倍 00-4倍
5-4 垂直方向的大小 00-1倍 00-2倍 00-3倍 00-4倍
3-0 =1111
****************************************************/
val=0;
val = (0b00<<6) | (0b00<<4) | 0b1111;
lcd_cmd(0xf1,val);
delay_ms(50);
}
// 选择工作图层
void lcd_worklayer(unsigned char n)
{
unsigned char a;
// 读取MAMR
a = lcd_read_com(0x12);
// 清除工作层设置位
a = a & 0b11111100;
// 重新设置工作层
lcd_cmd(0x12,a | n);
}
// 显示图层设置
void lcd_viewlayer(unsigned char m)
{
unsigned char a;
// 读取MAMR
a = lcd_read_com(0x12);
// 清除工作层设置位
a = a & 0b10000011;
// 重新设置工作层
lcd_cmd(0x12,(a | m) );
}
// LCD清屏
void lcd_cls(unsigned char page)
{
lcd_worklayer(page);
lcd_fullscreenfill(0x00);
}
// 设置为文本模式
void lcd_asc()
{
unsigned char a;
// 读取WLCR
a = lcd_read_com(0x00);
// 重新设置
lcd_cmd(0x00,a | (1<<3));
}
// 设置为图形模式
void lcd_pic()
{
unsigned char a;
// 读取WLCR
a = lcd_read_com(0x00);
// 重新设置
lcd_cmd(0x00,a & (~(1<<3)) );
}
// 在屏幕中指定位置显示一个点
void lcd_viewpiont(unsigned int x,unsigned char y)
{
unsigned char lx,ly,cx,t;
if( (x<_lcd_xmax) & (y<_lcd_ymax) )
{
lx=x>>3;
cx=x-(lx<<3);
ly=y;
lcd_gotoxy(lx,ly);
t=lcd_read_data();
lcd_data( t | (0x80>>cx) );
}
}
// 在屏幕中清除指定位置的点
void lcd_clspiont(unsigned int x,unsigned char y)
{
unsigned char lx,ly,cx,t;
if( (x<_lcd_xmax) & (y<_lcd_ymax) )
{
lx=x>>3;
cx=x-(lx<<3);
ly=y;
lcd_gotoxy(lx,ly);
t=lcd_read_data();
lcd_data( t & (~(0x80>>cx)) );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -