/* MAIN.C file
*
* Copyright (c) 2002-2005 STMicroelectronics
*/
#include"stm8s.h"
#include"stm8s105s4.h"
#include"stdio.h"
#define uchar unsigned char
#define uint unsigned int
_Bool LCD_RS @PC_ODR:2;
_Bool LCD_RW @PC_ODR:3;
_Bool LCD_EN @PE_ODR:6;
_Bool LCD_PSB @PC_ODR:1;
_Bool LCD_RST @PE_ODR:5;
_Bool DOT @PC_ODR:1;
uchar Key_Value=0;
char key_table[]=
{0xe7,0xd7,0xb7,0x77,/*第一行四个按键*/
0xeb,0xdb,0xbb,0x7b,/*第二行四个按键*/
0xed,0xdd,0xbd,0x7d,/*第三行四个按键*/
0xee,0xde,0xbe,0x7e/*第四行四个按键*/
};
void delaynms(unsigned int di) //延时
{
unsigned int da,db;
for(da=0;da
for(db=0;db<10;db++);
}
//函数功能:延时函数
void Delay(uchar nCount)
{
while (nCount != 0)
{
nCount--;
}
}
void delayNOP(void)
{_asm("nop");_asm("nop");_asm("nop");_asm("nop");_asm("nop");}
// 线反转法键盘扫描函数
char keyscan(void)
{
char temp1,temp2;
char hang;
char lie;
char key,i,final=0xff;
temp1 = 0x0f;
GPIO_DeInit(GPIOB);
GPIO_Init(GPIOB,GPIO_PIN_0,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_1,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_2,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_3,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_4,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_5,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_6,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_7,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Write(GPIOB,0x0f);
GPIO_Init(GPIOB,GPIO_PIN_0,GPIO_MODE_IN_FL_NO_IT);
GPIO_Init(GPIOB,GPIO_PIN_1,GPIO_MODE_IN_FL_NO_IT);
GPIO_Init(GPIOB,GPIO_PIN_2,GPIO_MODE_IN_FL_NO_IT);
GPIO_Init(GPIOB,GPIO_PIN_3,GPIO_MODE_IN_FL_NO_IT);
temp1 = GPIO_ReadInputData(GPIOB);
if(temp1!=0x0f)
{temp1 = GPIO_ReadInputData(GPIOB);}
hang = 0x0f&temp1;
Delay(0xff);
temp2 = 0xf0;
GPIO_Init(GPIOB,GPIO_PIN_0,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_1,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_2,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_3,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_4,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_5,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_6,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(GPIOB,GPIO_PIN_7,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Write(GPIOB,0xf0);
GPIO_Init(GPIOB,GPIO_PIN_4,GPIO_MODE_IN_FL_NO_IT);
GPIO_Init(GPIOB,GPIO_PIN_5,GPIO_MODE_IN_FL_NO_IT);
GPIO_Init(GPIOB,GPIO_PIN_6,GPIO_MODE_IN_FL_NO_IT);
GPIO_Init(GPIOB,GPIO_PIN_7,GPIO_MODE_IN_FL_NO_IT);
temp2 = GPIO_ReadInputData(GPIOB);
if(temp2!=0xf0)
{temp2 = GPIO_ReadInputData(GPIOB);}
lie = 0xf0&temp2;
key = hang | lie;
for(i=0;i<16;i++)
{
if(key == key_table[i])
{
final = i+1;
}
}
return final;
}
void TIM2_configuration(void)
{
TIM2_DeInit();//TIM2初始化
TIM2_TimeBaseInit(TIM2_PRESCALER_2,30000);//配置TIM2内部时钟基准,定时10ms
TIM2_ITConfig(TIM2_IT_UPDATE,ENABLE);//设置TIM2中断,更新
TIM2_Cmd(ENABLE);//开启TIM2使能
enableInterrupts();//开启总中断
}
void GPIO_Init1(void)
{
PB_DDR= 0xff;
PB_CR1 = 0xff;
PC_DDR= 0x0e;
PC_CR1 = 0x0e;
PE_DDR= 0x60;
PE_CR1 = 0x60;
}
void delay(int ms)
{
while(ms--)
{
uchar i;
for(i=0;i<250;i++);
}
}
void delay0(uchar x) //x*0.14MS
{
uchar i;
while(x--)
{
for (i = 0; i<113; i++);
}
}
//12864检查状态
void Check12864state(void)
{
PB_ODR=0xff;
LCD_EN = 0;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
GPIO_Init(GPIOB, GPIO_PIN_ALL, GPIO_MODE_IN_FL_NO_IT);
while((PB_IDR&0x80)==0x80);//等待空闲
LCD_EN = 0;
LCD_RS = 1;
LCD_RW = 0;
PB_DDR= 0xff;
PB_CR1 = 0xff;
}
void lcd_wdat(const uchar dat)
{
Check12864state();
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
PB_ODR= dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
delay(100);
}
void lcd_wcmd(const uchar cmd)
{
Check12864state();
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_asm("nop");
_asm("nop");
PB_ODR = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
delay(100);
}
void display(unsigned char x,unsigned char y,unsigned char *Str)
{
if((y>3)||(x>7))
return;//如果指定位置不在显示区域内,则不做任何写入直接返回
switch(y)
{
case 0:
lcd_wcmd(0x80+x);
break;
case 1:
lcd_wcmd(0x90+x);
break;
case 2:
lcd_wcmd(0x88+x);
break;
case 3:
lcd_wcmd(0x98+x);
break;
}
while(*Str>0)
{
lcd_wdat(*Str);
Str++;
}
}
void lcd_init(void)
{
LCD_PSB = 1; //并口方式
LCD_RST=1;
LCD_RST=0;
LCD_RST=1;
lcd_wcmd(0x34); //扩充指令操作
delay(5);
lcd_wcmd(0x30); //基本指令操作
delay(5);
lcd_wcmd(0x0C); //显示开,关光标
delay(5);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(5);
lcd_wcmd(0x06);
/*指定在资料写入或读取时,光标的移动方向,DDRAM的地址计数器(AC)加1。*/
delay(5);
}
void lcd_init2(void) //LCD显示图片(扩展)初始化程序
{
delaynms(10); //启动等待,等LCM讲入工作状态
lcd_wcmd(0x34);
lcd_wcmd(0x36); //扩充指令集
lcd_wcmd(0x3E); //(DL=8BITS,RE=1,G=1)
lcd_wcmd(0x02); //清DDRAM
}
/*****************图像显示***************************/
void photodisplay(uchar *bmp)
{
uchar i,j;
lcd_wcmd(0x34);//写数据时,关闭图像显示
for(i=0;i<32;i++)
{
lcd_wcmd(0x80+i);//先写入水平坐标值
lcd_wcmd(0x80);//写入垂直坐标值
for(j=0;j<16;j++)
lcd_wdat(*bmp++);
delaynms(1);
}
/********显示下半屏内容*****************/
for(i=0;i<32;i++)
{
lcd_wcmd(0x80+i);//先写入水平坐标值
lcd_wcmd(0x88);//写入垂直坐标值
for(j=0;j<16;j++)
lcd_wdat(*bmp++);
delaynms(1);
}
lcd_wcmd(0x36);//写完数据,开图像显示
lcd_wcmd(0x30);//回到基本指令集
}
void lcdtest(void) //图形方式下屏幕全黑
{
unsigned char i,j;
for(i=0;i<32;i++)
{ lcd_wcmd(0x80+i);lcd_wcmd(0x80);
for(j=0;j<16;j++) lcd_wdat(0xff);
}
for(i=0;i<32;i++)
{ lcd_wcmd(0x80+i);lcd_wcmd(0x88);
for(j=0;j<16;j++) lcd_wdat(0xff);
}
}
void lcdcls(void) //图形方式下清屏
{
unsigned char i,j;
for(i=0;i<32;i++)
{ lcd_wcmd(0x80+i);lcd_wcmd(0x80);
for(j=0;j<16;j++) lcd_wdat(0x00);
}
for(i=0;i<32;i++)
{ lcd_wcmd(0x80+i);lcd_wcmd(0x88);
for(j=0;j<16;j++) lcd_wcmd(0x00);
}
}
uchar readdat(void)
{
uchar Rdata;
Check12864state();
PB_ODR=0xff;
LCD_RS = 1;
LCD_RW = 1;
LCD_EN = 0;
delayNOP();
LCD_EN = 1;
delayNOP();
GPIO_Init(GPIOB, GPIO_PIN_ALL, GPIO_MODE_IN_FL_NO_IT);
Rdata=GPIO_ReadInputData(GPIOB);
LCD_EN = 0;
delayNOP();
PB_DDR= 0xff;
PB_CR1 = 0xff;
return Rdata;
}
void clr_screen(void)
{
lcd_wcmd(0x34);//扩充指令操作
delaynms(5);
lcd_wcmd(0x30);//基本指令操作
lcd_wcmd(0x01);//清屏
delaynms(5);
}
//填充GDRAM数据
void fill_GDRAM(uchar dat)//dat为填充数据
{
uchar i,j,k;
uchar GDRAM_X=0x80;//GDRAM水平地址
uchar GDRAM_Y=0x80;//GDRAM垂直地址
for(i=0;i<2;i++)
{
for(i=0;i<2;i++)
{
for(k=0;k<8;k++)
{
lcd_wcmd(0x34);
lcd_wcmd(GDRAM_Y+j);
lcd_wcmd(GDRAM_X+k);
lcd_wdat(dat);
lcd_wdat(dat);
}
}
GDRAM_X=0x88;
}
lcd_wcmd(0x36);
lcd_wcmd(0x30);
}
void gui_clear(void)
{
uchar i,j,k;
lcd_wcmd(0x34);
lcd_wcmd(0x34);
for(i=0;i<2;i++)
{
for(j=0;j<32;j++)
{
lcd_wcmd(0x80+j);
delay(1);
if(i==0)
{
lcd_wcmd(0x80);
delay(1);
}
else
{
lcd_wcmd(0x88);
}
for(k=0;k<8;k++)
{
lcd_wdat(0x00);
lcd_wdat(0x00);
delay(1);
}
}
}
lcd_wcmd(0x36);
lcd_wcmd(0x30);
}
void Fill_point(uchar x,uchar y,uchar color)
{
uchar x_Dyte,x_byte;//定义地址的字节在哪一位
uchar y_Dyte,y_byte;
uchar GDRAM_hbit,GDRAM_lbit;
lcd_wcmd(0x36);
//--XY坐标互换,及普通的X,Y坐标
x_Dyte=x/16;//计算在18个字节中的哪一位
x_byte=x&0x0f;//计算该字节中的哪一位
y_Dyte=y/32;//0为上屏,1位下屏
y_byte=y&0x1f;//计算在0——31中的哪一行
lcd_wcmd(0x80+y_byte);//设定行地址(Y坐标),即垂直地址
lcd_wcmd(0x80+x_Dyte+8*y_Dyte);//设定列地址(x坐标),并通8*y_Dyte选定上下屏,及水平地址
readdat();
GDRAM_hbit=readdat();
GDRAM_lbit=readdat();
delay(1);
lcd_wcmd(0x80+y_byte);//设定行地址(Y坐标),即垂直地址
lcd_wcmd(0x80+x_Dyte+8*y_Dyte);//设定列地址(x坐标),并通8*y_Dyte选定上下屏,及水平地址
delay(10);
if(x_byte<8)//判定其再高八位还是在低八位
{
if(color==1)
{
lcd_wdat(GDRAM_hbit|(0x01<<(7-x_byte)));
}
else
{
lcd_wdat(GDRAM_hbit|(0x01<<(~(7-x_byte))));
lcd_wdat(GDRAM_lbit);//显示GDRA区低八位
}
if(x_byte>=8)
{
lcd_wdat(GDRAM_hbit);
if(color==1)
{
lcd_wdat(GDRAM_hbit|(0x01<<(15-x_byte)));
}
else
{
lcd_wdat(GDRAM_hbit|(0x01<<(~(15-x_byte))));
}
}
lcd_wcmd(0x30);
}
}
/************向LCD指定位置画一条长度为Length的指定颜色的水平线 *****/
void Lcd_HoriLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color)
{
unsigned char i;
if(Length==0)
return;
for(i=0;i
{
Fill_point(x+i,y,Color);
}
}
/*******向LCD指定位置画一条长度为Length的指定颜色的垂直线 **********/
void Lcd_VertLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color)
{
unsigned char i;
if(Length==0)
return;
for(i=0;i
{
Fill_point(x,y+i,Color);
}
}
/*******************向lcd画矩形***************/
void lcd_rectangle(uchar x0,uchar y0,uchar x1,uchar y1,uchar color)
{
uchar temp;
if(x0>x1)
{
temp=x0;
x0=x1;
x1=temp;
}
if(y0>y1)
{
temp=y0;
y0=y1;
y1=temp;
}
Lcd_VertLine(x0,y0,y1-y0+1,color);
Lcd_VertLine(x1,y0,y1-y0+1,color);
Lcd_HoriLine(x0,y0,x1-x0+1,color);
Lcd_HoriLine(x1,y1,x1-x0+1,color);
}
main()
{
uchar i;
GPIO_Init1();
TIM2_configuration();
enableInterrupts();//开启总中断
delay(10); //延时
lcd_init(); //初始化LCD
while (1)
{
switch(Key_Value)
{
case 0:display(1,1,"0");break;
case 1:display(1,1,"1");break;
case 2:display(1,1,"2");break;
case 3:display(1,1,"3");break;
case 4:display(1,1,"4");break;
case 5:display(1,1,"5");break;
case 6:display(1,1,"6");break;
case 7:display(1,1,"7");break;
case 8:display(1,1,"8");break;
case 9:display(1,1,"9");break;
case 10:display(1,1,"10");break;
case 11:display(1,1,"11");break;
case 12:display(1,1,"12");break;
case 13:display(1,1,"13");break;
case 14:display(1,1,"14");break;
case 15:display(1,1,"15");break;
case 16:display(1,1,"16");break;
}
}
}
/*中断函数*/
#pragma vector=15__interrupt
void TIMER2_IRQHander(void)
{
Key_Value++;
if(Key_Value==16)
{
Key_Value==0;
}
TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
}
程序是这样的