📄 36.c
字号:
#pragma interrupt_handler timer:7 //TC1溢出中断
#include <io8515.h>
#include <macros.h>
#include <worddot.h> //自定义字符点阵码文件,存于include目录下#include <math.h> //数学运算定义,没有使用
#define Uchar unsigned char
//液晶显示器接口引脚定义
#define LCD_E (1 << 3) // PC3----E
#define LCD_DI (1 << 6) // PC6----D/I
#define LCD_RW (1 << 7) // PC7----R/W
#define LCD_CS1 (1 << 4) // PC4----CS1
#define LCD_CS2 (1 << 5) // PC5----CS2
#define LCD_CS3 (1 << 2) // PD2----CS3
#define lcd_set_e() (PORTC |= LCD_E) // 位置位,输出1
#define lcd_set_di() (PORTC |= LCD_DI)
#define lcd_set_rw() (PORTC |= LCD_RW)
#define lcd_clear_e() (PORTC &= ~LCD_E) // 位清零,输出0
#define lcd_clear_di() (PORTC &= ~LCD_DI)
#define lcd_clear_rw() (PORTC &= ~LCD_RW)
#define lcd_set_cs1() (PORTC |= LCD_CS1) // 片选
#define lcd_set_cs2() (PORTC |= LCD_CS2)
#define lcd_set_cs3() (PORTD |= LCD_CS3)
#define lcd_clear_cs1() (PORTC &= ~LCD_CS1)
#define lcd_clear_cs2() (PORTC &= ~LCD_CS2)
#define lcd_clear_cs3() (PORTD &= ~LCD_CS3)
#define LCD_BUSY 0x80 //LCM忙判断位
#define lcd_read_status() (PINA &= LCD_BUSY) //LCM忙判断
#define Datalcm PORTA //数据口
//常用操作命令和参数定义
#define DISPON 0x3f //显示on
#define DISPOFF 0x3e //显示off
#define DISPFIRST 0xc0 //显示起始行定义
#define SETX 0x40 //X定位设定指令(页)
#define SETY 0xb8 //Y定位设定指令(列)
//显示分区边界位置
#define MODL 0x00 //左区
#define MODM 0x40 //左区和中区分界
#define MODR 0x80 //中区和右区分界
#define LCMLIMIT 0xC0 //显示区的右边界
//全局变量定义
Uchar col,row,cbyte,timer1,timer2,statusm; //列x,行(页)y,输出数据
unsigned int speed=0x7fff;
//函数列表
void Lcminit(void); //液晶模块初始化
void Delay(Uchar); //延时,入口数为Ms
void lcdbusyL(void); //busy判断、等待(左区)
void lcdbusyM(void); //busy判断、等待(中区)
void lcdbusyR(void); //busy判断、等待(右区)
void Putedot(Uchar x,Uchar y,Uchar flash *Lib,Uchar Order,Uchar widthw);
void Wrdata(Uchar); //数据输出给LCM
void Lcmcls( void ); //LCM全屏幕清零(填充0)
void wtcom(void); //公用busy等待
void Locatexy(void); //光标定位
void WrcmdL(Uchar); //左区命令输出
void WrcmdM(Uchar); //中区命令输出
void WrcmdR(Uchar); //右区命令输出
void Putstr(Uchar x,Uchar y,Uchar flash *puts,Uchar i); //字符串输出
void Rollscreen(Uchar x); //屏幕向上滚动演示
void Rddata(void); //从液晶片上读数据
void point(void); //打点
void Linexy(Uchar x0,Uchar y0,Uchar xt,Uchar yt);
void main_init(void);
void timer(void);
void circle(Uchar Ox,Uchar Oy,Uchar Rx);
//数组列表
Uchar flash Ezk[]; //ASCII常规字符点阵码表
Uchar flash Hzk[]; //自用汉字点阵码表
Uchar flash STR1[]; //自定义字符串
Uchar flash STR2[]; //flash "=" code(keil c51)
Uchar flash STR3[]; //
Uchar flash STR4[]; //
//演示主程序
void main(void)
{
Uchar x=0;
DDRD = 0xFF; //|= LCD_CS3;定义输出位 DDRC = 0xFF; //定义为输出口
statusm&=0<<7;
main_init();
Delay(5); //延时,等待外设准备好
Lcminit(); //液晶模块初始化,包括全屏幕清屏
Putstr(0,0,STR3,24); //第一行字符输出,24字节
Putstr(0,2,STR1,12); //第二行字符输出,12字节(汉字)
Putstr(0,4,STR3,24); //第三行字符输出,24字节
Putstr(0,6,STR4,24); //第四行字符输出,12字节
Linexy(0,0,191,0); //line (0,0)-(191,0)
Linexy(191,0,191,32); //line (191,0)-(191,32)
Linexy(191,32,0,32); //line (191,32)-(0,32)
Linexy(0,32,0,0); //line (0,32)-(0,0)
Linexy(1,15,191,15); //line (1,15)-(191,15)
Linexy(0,63,44,33); //line (0,63)-(44,33)
Linexy(44,33,191,63); //line (44,33)-(191,63)
circle(46,49,12); //画一个圆
circle(46,49,11);
//statusm|=1<<7;
while(1){
Rollscreen(x); //定位新的显示起始行
x++;
Delay(20); //延时,控制滚动速度
};
}
//初始化8515定时寄存器
void main_init(void)
{
TCCR1A = 0x00;
TCCR1B = 0x00; //停止定时器1
TCNT1H = 0x00; //清除定时器1
TCNT1L = 0x00;
TIMSK = 0x80; // 开放定时器1溢出中断
SREG |= 0x80;
TCCR1B = 0x01; //启动定时器1,预分频比例1
}
//在定时器中断中做多个分级定时
void timer()
{
timer1--;
if (timer2<0x80) speed+=0x100;
else speed-=0x200;
if (statusm&0x80){
timer2++;
col = (speed>>8)|timer1;
row = (timer2&0x1f)+32;
point();}
}
//画圆。数学方程(X-Ox)^2+(Y-Oy)^2=Rx^2
void circle(Uchar Ox,Uchar Oy,Uchar Rx)
{
unsigned int xx,rr,xt,yt,rs;
yt=Rx;
rr=Rx*Rx+1; //补偿 1 修正方形
rs=(yt+(yt>>1))>>1; //(*0.75)分开1/8圆弧来画
for (xt=0;xt<=rs;xt++)
{
xx=xt*xt;
while ((yt*yt)>(rr-xx))yt--;
col=Ox+xt; //第一象限
row=Oy-yt;
point();
col=Ox-xt; //第二象限
point();
row=Oy+yt; //第三象限
point();
col=Ox+xt; //第四象限
point();
//45度镜象画另一半
col=Ox+yt; //第一象限
row=Oy-xt;
point();
col=Ox-yt; //第二象限
point();
row=Oy+xt; //第三象限
point();
col=Ox+yt; //第四象限
point();
}
}
//画线。任意方向的斜线,直线数学方程 aX+bY=1
void Linexy(Uchar x0,Uchar y0,Uchar xt,Uchar yt)
{
register Uchar t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
int incx,incy;
delta_x=xt-x0; //计算坐标增量
delta_y=yt-y0;
col = x0;
row = y0;
if(delta_x>0) incx=1; //设置单步方向
else if( delta_x==0 ) incx=0; //垂直线
else {incx=-1;delta_x=-delta_x;}
if(delta_y>0) incy=1;
else if( delta_y==0 ) incy=0; //水平线
else {incy=-1;delta_y=-delta_y;}
if( delta_x > delta_y ) distance=delta_x; //选取基本增量坐标轴
else distance=delta_y;
for( t=0;t <= distance+1; t++ )
{ //画线输出
point(); //画点
xerr += delta_x ;
yerr += delta_y ;
if( xerr > distance )
{
xerr-=distance;
col+=incx;
}
if( yerr > distance ) {
yerr-=distance;
row+=incy;
}
}
}
//画点
void point(void)
{
Uchar x1,y1,x,y;
x1=col;
y1=row;
row=y1>>3; //取Y方向分页地址
Rddata();
y=y1&0x07; //字节内位置计算
Wrdata(cbyte|1<<y); //画上屏幕
col=x1; //恢复xy坐标
row=y1;
}
//屏幕滚动定位
void Rollscreen(Uchar x)
{
cbyte = DISPFIRST|x; /*定义显示起始行为x?*/
WrcmdL(cbyte);
WrcmdM(cbyte);
WrcmdR(cbyte);
}
//一个字串的输出
void Putstr(Uchar x,Uchar y,Uchar flash *puts,Uchar i)
{
Uchar j,W,wordx;
for (j=0;j<i;j++)
{
wordx = puts[j];Delay(2);
if (wordx&0x80)
{
Putedot(x,y,Hzk,wordx&0x7f,16); //只保留低7位
}
else Putedot(x,y,Ezk,wordx-0x20,8); //ascii码表从0x20开始
x=col;
y=row;
}
}
//字符点阵码数据输出
void Putedot(Uchar x,Uchar y,Uchar flash *Lib,Uchar Order,Uchar widthw)
{
Uchar i;
int xi; //偏移量,字符量少的可以定义为Uchar
col = x; //暂存x,y坐标,已备下半个字符使用
row = y;
xi=Order * widthw<<1; //每个字符widthw列
//上半个字符输出
for(i=0;i<widthw;i++)
{
cbyte = Lib[xi]; //取点阵码,rom数组
Wrdata(cbyte); //写输出一字节
xi++;
col++;
if (col==LCMLIMIT){col=0;row+=2;}; //下一列,如果列越界换行
if (row>7) row=0; //如果行越界,返回首行
} //上半个字符输出结束
col = x; //列对齐
row = y+1; //指向下半个字符行
//下半个字符输出
for(i=0;i<widthw;i++)
{
cbyte = Lib[xi]; //取点阵码
Wrdata(cbyte); //写输出一字节
xi++;
col++;
if (col==LCMLIMIT){col=0;row+=2;}; //下一列,如果列越界换行
if (row>7) row=1; //如果行越界,返回首行
} //下半个字符输出结束
row=y;
} //整个字符输出结束
//清屏,全屏幕清零
void Lcmcls( void )
{
for(row=0;row<8;row++)
for(col=0;col<LCMLIMIT;col++) Wrdata(0);
}
// 从液晶片上读数据,保留在全局变量中
void Rddata(void)
{
Locatexy(); //坐标定位,返回时保留分区状态不变
DDRA = 0; //改变PA口的状态,作为输入口
Datalcm=0xFF;
lcd_set_di(); //数据
lcd_set_rw(); //读数据
lcd_set_e();
NOP(); //读入到LCM
cbyte = PINA; //虚读一次
lcd_clear_e();
Locatexy(); //坐标定位,返回时保留分区状态不变
DDRA = 0;
Datalcm=0xFF;
lcd_set_di(); //数据
lcd_set_rw(); //读数据
lcd_set_e();
NOP(); //读入到LCM
cbyte = PINA; //从数据口读数据,真读
lcd_clear_e();NOP();
DDRA = 0xFF; //改变PA口的状态,作为输出口
}
//数据写输出
void Wrdata(Uchar X)
{
Locatexy(); //坐标定位,保留分区状态不变
wtcom();
lcd_set_di(); //数据输出
lcd_clear_rw();
NOP(); //写输出
Datalcm = X; //数据输出到数据口
lcd_set_e(); //LCM读入
NOP();
lcd_clear_e();
}
//命令输出到左区控制口
void WrcmdL(Uchar X)
{
lcdbusyL(); //确定分区,返回时保留分区状态不变
lcd_clear_di(); //命令操作
lcd_clear_rw();NOP(); //写输出
Datalcm = X; //数据写到数据口
lcd_set_e();NOP();lcd_clear_e(); //LCM读入
}
//命令输出到中区控制口
void WrcmdM(Uchar X)
{
lcdbusyM(); //确定分区,保留分区状态不变
lcd_clear_di(); //命令操作
lcd_clear_rw();NOP(); //写输出
Datalcm = X; //命令写到数据口
lcd_set_e();NOP();lcd_clear_e(); //LCM读入
}
//命令输出到右区控制口
void WrcmdR(Uchar X)
{
lcdbusyR(); //确定分区,保留分区状态不变
lcd_clear_di(); //命令操作
lcd_clear_rw();NOP(); //写输出
Datalcm = X; //命令输出到数据口
lcd_set_e();NOP();lcd_clear_e(); //读入到LCM
}
//分区操作允许等待,返回时保留分区选择状态
void lcdbusyL(void)
{
lcd_clear_cs1(); //CLR CS1
lcd_set_cs2(); //SETB CS2
lcd_set_cs3(); //SETB CS3
wtcom(); //等待
}
void lcdbusyM(void)
{
lcd_set_cs1(); //SETB CS1
lcd_clear_cs2(); //CLR CS2
lcd_set_cs3(); //SETB CS3
wtcom();
}
void lcdbusyR(void)
{
lcd_set_cs1(); //SETB CS1
lcd_set_cs2(); //SETB CS2
lcd_clear_cs3(); //CLR CS3
wtcom();
}
void wtcom(void)
{
DDRA = 0;
lcd_clear_di(); //CLR DI
lcd_set_rw(); //SETB RW
Datalcm = 0xFF;
lcd_set_e();NOP();
while(lcd_read_status());
lcd_clear_e();
DDRA=0xFF;
}
//根据设定的坐标数据,定位LCM上的下一个操作单元位置
void Locatexy(void)
{
Uchar x,y;
switch (col&0xc0)
{ //条件分支执行
case 0:
{lcdbusyL();
break;
} //左区
case 0x40:
{
lcdbusyM();
break;
} //中区
case 0x80:
{
lcdbusyR();
break;
} //右区
}
x = col&0x3F|SETX;
y = row&0x07|SETY;
wtcom();
lcd_clear_di();
lcd_clear_rw();
NOP();
Datalcm = y;
lcd_set_e();
NOP();
lcd_clear_e();
wtcom();
lcd_clear_di();
lcd_clear_rw();
NOP();
Datalcm = x;
lcd_set_e();
NOP();
lcd_clear_e();
}
//液晶屏初始化
void Lcminit(void)
{
cbyte = DISPOFF; //关闭显示屏
WrcmdL(cbyte);
WrcmdM(cbyte);
WrcmdR(cbyte);
cbyte = DISPON; //打开显示屏
WrcmdL(cbyte);
WrcmdM(cbyte);
WrcmdR(cbyte);
cbyte = DISPFIRST; //定义显示起始行为零
WrcmdL(cbyte);
WrcmdM(cbyte);
WrcmdR(cbyte);
Lcmcls(); //清屏
}
//延时
void Delay(Uchar MS)
{
timer1=MS;
while(timer1);
}
//定义字符串数组
Uchar flash STR1[]=
{
0x80,0x81,0x82,0x83,0x84,0x85,
0x86,0x87,0x88,0x89,0x8a,0x8B
};
Uchar flash STR2[]="Our friend over the wold";
Uchar flash STR3[]="Program by ICCAVR V6.21B";
Uchar flash STR4[]="Thank you 1234567890";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -