目录 ampire128*64
- Proteus和Keils程序下载(百度网盘)
- ampire128*64 (preteus)
-
- 概述
- ampire128*64的仿真实物图
- 关于ampire128*64的引脚接线
- 仿真程序编写(keil)
-
- 查询 忙 状态 void check_busy()
- 写命令 void LCD_write_command(char cmdata)
- 写数据 void LCD_write_data(char wodata)
- LCD初始化 void LCD_Init()
- 设置 LCD 显示的坐标 void set_xy(char x, char y)
- 显示 16*16 像素点的汉字 void disp_hz(char R,char L,char *p)
- 显示 16*8 像素点的字母或符号 void disp_hz(char R,char L,char *p)
- 主函数 int main()
- 总代码
Proteus和Keils程序下载(百度网盘)
链接:https://pan.baidu.com/s/16d4WXDRUduuw7KPAu1_-mQ
提取码:nbxy
(有一说一,CSDN上传资源就算本来下载积分设成0,也会自己调高,真的难受,还是放链接了)
ampire128*64 (preteus)
概述
ampire128*64 就是一块lcd显示屏,可以看成是 128**64 个灯泡组成
“写数据”——函数控制灯泡的亮灭
“写命令”——函数执行 lcd 本身自带的命令
要让 LCD 显示东西
- 把 LCD 初始化
- 将要显示的 字模数据 写入 DDRAM ,就可以控制灯泡的亮灭
- PCtoLCD2002(取字模软件),使用该软件取出要使用的字模数据
- 使用说明:修改字模选项
- PCtoLCD2002(取字模软件),使用该软件取出要使用的字模数据
ampire128*64的仿真实物图
芯片用的是stm32f401VE
芯片仿真没接电源,实物一定要接
关于ampire128*64的引脚接线
CS1:左半屏选择引脚,低电平有效。该引脚有效时左半屏幕操作有效
CS2:右半屏选择引脚,低电平有效。该引脚有效时右半屏幕操作有效
GND:电源地
VCC:电源正
V0:LCD的驱动电压,用来调节LCD背景深浅对比度(这个脚悬空不接就可以)
RS:命令/数据控制引脚。该脚为高电平是DB数据线上传输的是数据,该脚为低电平是DB数据线上传输的是命令
R/W:读/写控制引脚。该脚为高电平时从LCD模块中毒数据,该脚为低电平时写数据到LCD模块中。
E:LCD读写使能引脚
DB7 - DB0 :数据总线
RST:复位脚,低电平复位(直接接高电平)
-Vout:LCD的驱动电源(接-10v的电源)
不懂没关系,照图接引脚就行
仿真程序编写(keil)
查询 忙 状态 void check_busy()
void check_busy()
{
char a=0;
for(a=0;a<200;a++); //此处为延时,一段时间后确保处于空闲状态
//此处为状态查询,查询忙状态,没有使用成功,以后再调试
//RW=1;
GPIO_WriteBit(GPIOB,LCD_RW,1);
//RS=0;
GPIO_WriteBit(GPIOB,LCD_RS,0);
//E=1;
GPIO_WriteBit(GPIOB,LCD_EA,1);
while(1)
{
//E=0;
GPIO_WriteBit(GPIOB,LCD_EA,0);
//这里就是要检测 DB7 引脚的电平,低电平说明不忙,可以写入数据或命令
if ( DB7引脚 == 0)
break;
//设定循环次数,防止无限循环
a++;
if(a>10)
break;
}
//E=1;
GPIO_WriteBit(GPIOB,LCD_EA,1);
}
这个函数用来检查lcd是否处于 忙 状态
如果 LCD 处于 忙 状态,那就等着
直到LCD不忙的时候再写命令或数据
正常来说每次写命令或写数据的时候要先调用此函数,查 忙 状态,proteuw仿真的时候有点小bug,会一直处于 忙状态 ,就不调用了
写命令 void LCD_write_command(char cmdata)
void LCD_write_command(char cmdata)
{
//这里本来要调用查 忙 函数,仿真可以不调用
//check_busy();
//LCD_RS=0;
GPIO_WriteBit(GPIOB,LCD_RS,0);
//LCD_RW=0;
GPIO_WriteBit(GPIOB,LCD_RW,0);
//LCD_EA=1; //开使能
GPIO_WriteBit(GPIOB,LCD_EA,1);
// D0-D7 =cmdata;
GPIO_Write(GPIOA,cmdata);
//LCD_EA=0; //关使能
GPIO_WriteBit(GPIOB,LCD_EA,0);
delay_us(15);
}
写数据 void LCD_write_data(char wodata)
void LCD_write_data(char wodata)
{
//这里本来要调用查 忙 函数,仿真可以不调用
//check_busy();
//LCD_RS=1;
GPIO_WriteBit(GPIOB,LCD_RS,1);
//LCD_RW=0;
GPIO_WriteBit(GPIOB,LCD_RW,0);
//LCD_EA=1;
GPIO_WriteBit(GPIOB,LCD_EA,1);
//D0-D7 = wodata;
GPIO_Write(GPIOA,wodata);
//LCD_EA=0;
GPIO_WriteBit(GPIOB,LCD_EA,0);
delay_us(15);
}
LCD初始化 void LCD_Init()
void LCD_Init()
{
LCD_write_command(0x30); //
delay_us(4);
LCD_write_command(0x0c); //开显示,关光标,不闪烁
delay_us(10);
LCD_write_command(0x01); //清除显示
delay_us(10);
LCD_write_command(0x06); //光标的移动方向向左,DDRM的地址计数器(AC)加1
delay_us(10);
}
这里初始化的命令照搬就行,每次初始化基本都是这样,想要其他初始化的可以去查 ampire128 的指令集
设置 LCD 显示的坐标 void set_xy(char x, char y)
void set_xy(char x, char y)
{
if( y>=64 )
{
GPIO_WriteBit(GPIOB,CS1,1);
GPIO_WriteBit(GPIOB,CS2,0);
y = y-64;
}
else
{
GPIO_WriteBit(GPIOB,CS1,0);
GPIO_WriteBit(GPIOB,CS2,1);
}
LCD_write_command( 0x40 | y );
delay_us(15);
LCD_write_command( 0xb8 | x );
}
显示 16*16 像素点的汉字 void disp_hz(char R,char L,char *p)
void disp_hz(char R,char L,char *p)//汉字 16*16
{
char i;
for(i=0;i<16;i++)
{
set_xy(2*R,16*L+i); //设定显示位置,每个汉字16*16个点,显示时每行8*16个点,所以需要两行8*32个点,此处为第一行
LCD_write_data(p[i]); //写入DDRAM
set_xy(2*R+1,16*L+i); //第二行
LCD_write_data(p[i+16]);
}
}
显示 16*8 像素点的字母或符号 void disp_hz(char R,char L,char *p)
void disp_zf(char R,char L,char *p)//字母符号 16*8
{
char i;
for(i=0;i<8;i++)
{
set_xy(2*R,8*L+i); //设定显示位置,每个字母16*8个点,显示时每行8*8个点,所以需要两行8*16个点,此处为第一行
LCD_write_data(p[i]);
set_xy(2*R+1,8*L+i); //第二行
LCD_write_data(p[i+8]);
}
}
主函数 int main()
int main()
{
char k=0;
//初始化计时器
systick_init();
//初始化 GPIO
GPIO_INIT();
// LCD 初始化
LCD_Init();
//lcd显示“温度”
for(k=0;k<3;k++)
disp_hz(1,0+k,Chra[k]);
//lcd显示“湿度”
for(k=0;k<3;k++)
disp_hz(2,0+k,Chra[k+3]);
while(1)
{
}
return 0;//主函数的返回
}
总代码
#include <stdio.h>//单片机工程可以不用
#include <stm32f4xx.h>//这个头文件一定要包含 ---这个头文件官方帮我们定义好了所有寄存器的地址
//适合LM016L液晶显示器
#define LCD_RS GPIO_Pin_0
#define LCD_RW GPIO_Pin_1
#define LCD_EA GPIO_Pin_2
#define CS1 GPIO_Pin_5
#define CS2 GPIO_Pin_4
/*----lcd字模定义----------------------------------------------------------------------------------*/
char Max[3][16] =
{
// M(0) a(1) x(2)
{0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x01,0x3E,0x01,0x3F,0x20,0x00},/*"M",0*/
{0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x19,0x24,0x24,0x12,0x3F,0x20,0x00},/*"a",1*/
{0x00,0x80,0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x20,0x31,0x0E,0x2E,0x31,0x20,0x00}/*"x",2*/
};
char Number[10][16] =
{
{0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00},/*"0",9*/
{0x00,0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00},/*"1",0*/
{0x00,0x70,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},/*"2",1*/
{0x00,0x30,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x18,0x20,0x21,0x21,0x22,0x1C,0x00},/*"3",2*/
{0x00,0x00,0x80,0x40,0x30,0xF8,0x00,0x00,0x00,0x06,0x05,0x24,0x24,0x3F,0x24,0x24},/*"4",3*/
{0x00,0xF8,0x88,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x20,0x20,0x20,0x11,0x0E,0x00},/*"5",4*/
{0x00,0xE0,0x10,0x88,0x88,0x90,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x20,0x1F,0x00},/*"6",5*/
{0x00,0x18,0x08,0x08,0x88,0x68,0x18,0x00,0x00,0x00,0x00,0x3E,0x01,0x00,0x00,0x00},/*"7",6*/
{0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00},/*"8",7*/
{0x00,0xF0,0x08,0x08,0x08,0x10,0xE0,0x00,0x00,0x01,0x12,0x22,0x22,0x11,0x0F,0x00}/*"9",8*/
};
char Chra[6][32] =
{
{0x10,0x60,0x02,0x8C,0x00,0x00,0xFE,0x92,
0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00,
0x04,0x04,0x7E,0x01,0x40,0x7E,0x42,0x42,
0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00},/*"温",0*/
{0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0x25,
0x26,0x24,0xFC,0x24,0x24,0x24,0x04,0x00,
0x40,0x30,0x8F,0x80,0x84,0x4C,0x55,0x25,
0x25,0x25,0x55,0x4C,0x80,0x80,0x80,0x00},/*"度",1*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*":",0*/
{0x10,0x60,0x02,0x8C,0x00,0xFE,0x92,0x92,
0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00,
0x04,0x04,0x7E,0x01,0x44,0x48,0x50,0x7F,
0x40,0x40,0x7F,0x50,0x48,0x44,0x40,0x00},/*"湿",2*/
{0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0x25,
0x26,0x24,0xFC,0x24,0x24,0x24,0x04,0x00,
0x40,0x30,0x8F,0x80,0x84,0x4C,0x55,0x25,
0x25,0x25,0x55,0x4C,0x80,0x80,0x80,0x00},/*"度",3*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*":",0*/
};
/*------------------滴答定时器模块----------------------------------------------------------*/
void systick_init(void)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
}
void delay_us(unsigned int us)
{
unsigned int set_time = us*84;//得到设定值 us*84<16777215 us<199728
unsigned int tmp;
//初始化
SysTick->LOAD = set_time;//把当前获取需要的延时的时间设定值丢给LOAD寄存器 24bit
SysTick->VAL = 0;//先清空计数器的当前值 写0 之后再开启定时器后 会将LOAD的设定值自动装载进VAL
//开滴答定时器
SysTick->CTRL |= 0x01;//给最低位1 开滴答定时器
while(1)
{
tmp = SysTick->CTRL;//读取
//只要该条件为非零 就表示已经递减计数到0
if(tmp & 0x10000)
{
break;//跳出
}
}
SysTick->VAL = 0;//把计数值清零
SysTick->CTRL &= (~0x01) ;//关闭定时器 0xFFFFFFFE 1110
//0|任何位不会改变该位
//1|任何位都会变为1
}
void delay_ms(unsigned int ms)
{
unsigned int set_time = ms*84000;//得到设定值 us*84000<16777215 us<199.728 最高这一次延时
unsigned int tmp;
//初始化
SysTick->LOAD = set_time;//把当前获取需要的延时的时间设定值丢给LOAD寄存器 24bit
SysTick->VAL = 0;//先清空计数器的当前值 写0 之后再开启定时器后 会将LOAD的设定值自动装载进VAL
//开滴答定时器
SysTick->CTRL |= 0x01;//给最低位1 开滴答定时器
while(1)
{
tmp = SysTick->CTRL;//读取
//只要该条件为非零 就表示已经递减计数到0
if(tmp & 0x10000)
{
break;//跳出
}
}
SysTick->VAL = 0;//把计数值清零
SysTick->CTRL &= (~0x01) ;//关闭定时器 0xFFFFFFFE 1110
//0|任何位不会改变该位
//1|任何位都会变为1
}
void delay_s(unsigned int s)
{
while(--s)
{
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
}
}
/*--------lcd模块-------------------------------------------------------------------------------------------------
*/
void check_busy()
{
char a=0;
for(a=0;a<200;a++); //此处为延时,一段时间后确保处于空闲状态
/* //此处为状态查询,查询忙状态,没有使用成功,以后再调试
RW=1;
RS=0;
E=1;
while(1)
{
E=1;
if(!(P0&0x80))
break;
a++;
if(a>10)
break;
}
E=1;
*/
}
//写命令
void LCD_write_command(char cmdata)
{
//check_busy();
//LCD_RS=0;
GPIO_WriteBit(GPIOB,LCD_RS,0);
//LCD_RW=0;
GPIO_WriteBit(GPIOB,LCD_RW,0);
//LCD_EA=1; //开使能
GPIO_WriteBit(GPIOB,LCD_EA,1);
// D0-D7 =cmdata;
GPIO_Write(GPIOA,cmdata);
//LCD_EA=0; //关使能
GPIO_WriteBit(GPIOB,LCD_EA,0);
delay_us(15);
}
//写数据
void LCD_write_data(char wodata)
{
//check_busy();
//LCD_RS=1;
GPIO_WriteBit(GPIOB,LCD_RS,1);
//LCD_RW=0;
GPIO_WriteBit(GPIOB,LCD_RW,0);
//LCD_EA=1;
GPIO_WriteBit(GPIOB,LCD_EA,1);
//D0-D7 = wodata;
GPIO_Write(GPIOA,wodata);
//LCD_EA=0;
GPIO_WriteBit(GPIOB,LCD_EA,0);
delay_us(15);
}
//LCD初始化
void LCD_Init()
{
LCD_write_command(0x30); //
delay_us(4);
LCD_write_command(0x0c); //开显示,关光标,不闪烁
delay_us(10);
LCD_write_command(0x01); //清除显示
delay_us(10);
LCD_write_command(0x06); //光标的移动方向向左,DDRM的地址计数器(AC)加1
delay_us(10);
}
void set_xy(char x, char y)
{
if( y>=64 )
{
GPIO_WriteBit(GPIOB,CS1,1);
GPIO_WriteBit(GPIOB,CS2,0);
y = y-64;
}
else
{
GPIO_WriteBit(GPIOB,CS1,0);
GPIO_WriteBit(GPIOB,CS2,1);
}
LCD_write_command( 0x40 | y );
delay_us(15);
LCD_write_command( 0xb8 | x );
}
void disp_hz(char R,char L,char *p)//汉字 16*16
{
char i;
for(i=0;i<16;i++)
{
set_xy(2*R,16*L+i); //设定显示位置,每个汉字16*16个点,显示时每行8*16个点,所以需要两行8*32个点,此处为第一行
LCD_write_data(p[i]); //写入DDRAM
set_xy(2*R+1,16*L+i); //第二行
LCD_write_data(p[i+16]);
}
}
void disp_zf(char R,char L,char *p)//字母符号 16*8
{
char i;
for(i=0;i<8;i++)
{
set_xy(2*R,8*L+i); //设定显示位置,每个字母16*8个点,显示时每行8*8个点,所以需要两行8*16个点,此处为第一行
LCD_write_data(p[i]);
set_xy(2*R+1,8*L+i); //第二行
LCD_write_data(p[i+8]);
}
}
void GPIO_INIT(void)
{
//使能指定的GPIO模块时钟--默认复位后开机时钟不会全部提供给各个模块 使用时需要自己开启
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_InitTypeDef aaa;
aaa.GPIO_Pin = GPIO_Pin_All;//引脚号选择 PA0 也要按照官方的填法 怎么填 去头文件 stm32f4xx_gpio.h
aaa.GPIO_Mode = GPIO_Mode_OUT;//输出模式
aaa.GPIO_OType = GPIO_OType_PP;//推挽输出
aaa.GPIO_Speed = GPIO_High_Speed;//高速
//写入
GPIO_Init(GPIOC,&aaa);//&
GPIO_Init(GPIOA,&aaa);//&
GPIO_Init(GPIOB,&aaa);//&
//控制引脚
GPIO_WriteBit(GPIOC, GPIO_Pin_All , 1);
}
int main()
{
char k=0;
//初始化计时器
systick_init();
//初始化 GPIO
GPIO_INIT();
// LCD 初始化
LCD_Init();
//lcd显示“温度”
for(k=0;k<3;k++)
disp_hz(1,0+k,Chra[k]);
//lcd显示“湿度”
for(k=0;k<3;k++)
disp_hz(2,0+k,Chra[k+3]);
while(1)
{
}
return 0;//主函数的返回
}