Files
motor/BSP/drv_st7920.c
T
2025-03-26 12:47:09 +08:00

502 lines
15 KiB
C

//***************************************************************************
//连线表: CPU=89C52 *
//RS=P3.0 RW=P3.1 E=P3.2 *
//FOSC=12MHz D0-D7=P1.0-P1.7 *
//***************************************************************************
#include "drv_st7920.h"
enum {
LCD_CMD = 0x00,
LCD_DAT = 0x01
};
#define LCD_CLEAR 0x01
#define LCD_HOME 0x02
#define LCD_CLR 0x01
#define LCD_CLR 0x01
#define LCD_CLR 0x01
#define LCD_CLR 0x01
#define LCD_CLR 0x01
#define LCD_CLR 0x01
/***************************************************************************************
* 2020.11.20
* LED12864模块
* 管脚号 管脚名称 LEVER 管脚功能描述
* 1 VSS 0 电源地
* 2 VDD +5.0V 电源电压
* 3 V0 - 液晶显示器驱动电压
* 4 D/I(RS) H/L D/I=“H” 表示DB7∽DB0为显示数据
* D/I=“L” 表示DB7∽DB0为显示指令数据
* 5 R/W(SID) H/L R/W=“H”,E=“H”数据被读到DB7∽DB0
* R/W=“L”,E=“H→L”数据被写到IR或DR
* 6 E(CLK) H/L R/W=“L”,E信号下降沿锁存DB7∽DB0
* R/W=“H”,E=“H”DDRAM数据读到DB7∽DB0
* 7 DB0 H/L 数据线
* 8 DB1 H/L 数据线
* 9 DB2 H/L 数据线
* 10 DB3 H/L 数据线
* 11 DB4 H/L 数据线
* 12 DB5 H/L 数据线
* 13 DB6 H/L 数据线
* 14 DB7 H/L 数据线
* 15 PSB(CS1) H/L 并/串行接口选择:H-并行 L-串行
* 16 NC(CS2) 空脚
* 17 RST H/L 复位信号,低电平复位
* 18 VOUT -10V LCD驱动负电压
* 19 LED+ + LED背光板电源
* 20 LED- - LED背光板电源
*********************************************************************************************/
/*****************************
屏幕与DDRAM地址的对应关系
第一字 第二字 ......... 第七字 第八字
第一行 80H 81H ......... 82H 87H
第二行 90H 91H ......... 92H 97H
第三行 88H 89H ......... 8EH 8FH
第四行 98H 99H ......... 9EH 9FH
第n行
*******************************/
unsigned char GDRAM[64][16] = { //横向取模,无字节倒序 64行,16列
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"未命名文件",0*/
};
void init_lcd (void);
void cn_disp(unsigned char *cn);
void txt_disp(unsigned char *cn,unsigned char adr);
void gra_disp(unsigned char *img);
void lat_disp(unsigned char data1,unsigned char data2);
void con_disp(unsigned char data1,unsigned char x0,unsigned char y0,unsigned char xl,unsigned char yl);
void lcd_txt_clr(void);
void lcd_gra_clr(void);
void LCD_CheckBusy(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
//修改为输入
GPIO_InitStruct.Pin = LCD_DB0_Pin|LCD_DB1_Pin|LCD_DB2_Pin|LCD_DB3_Pin
|LCD_DB4_Pin|LCD_DB5_Pin|LCD_DB6_Pin|LCD_DB7_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_PinState status;
RS(0);
RW(1); //读出数据,RW=1
GPIOA->BSRR = 0x00ff;
GPIOA->BRR = 0x0000;
EN(0);
EN(1);
do
{
status = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7);//接收BF位,判断是否忙
}while(status);
EN(0);
//修改为输出
GPIO_InitStruct.Pin = LCD_DB0_Pin|LCD_DB1_Pin|LCD_DB2_Pin|LCD_DB3_Pin
|LCD_DB4_Pin|LCD_DB5_Pin|LCD_DB6_Pin|LCD_DB7_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void LCD_Write(unsigned char type,unsigned char data)
{
LCD_CheckBusy();
RS(type);
RW(0); //write
EN(1);
//整个端口赋值
GPIOA->BSRR = data & 0x00ff;
GPIOA->BRR = ~data & 0x00ff;
EN(0);
}
unsigned char LCD_Read(void)
{
unsigned char data = 0x00;
LCD_CheckBusy();
GPIO_InitTypeDef GPIO_InitStruct = {0};
//修改为输入
GPIO_InitStruct.Pin = LCD_DB0_Pin|LCD_DB1_Pin|LCD_DB2_Pin|LCD_DB3_Pin
|LCD_DB4_Pin|LCD_DB5_Pin|LCD_DB6_Pin|LCD_DB7_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
RS(1);
RW(1); //write
EN(0);
EN(1);
data = GPIOA->IDR & 0xff;
EN(0);
//修改为输出
GPIO_InitStruct.Pin = LCD_DB0_Pin|LCD_DB1_Pin|LCD_DB2_Pin|LCD_DB3_Pin
|LCD_DB4_Pin|LCD_DB5_Pin|LCD_DB6_Pin|LCD_DB7_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
return data;
}
void LCD_Init (void)
{
PS(0x01);//选择并口模式
LCD_Write(LCD_CMD,0x30); /*30---功能设定,8-bit模式*/
LCD_Write(LCD_CMD,0x30); /*30---功能设定,基本指令*/
LCD_Write(LCD_CMD,0x08); /*设置显示、光标、闪烁全关*/
LCD_Write(LCD_CMD,0x01); /*清屏,地址指针指向00H*/
LCD_Write(LCD_CMD,0x06); /*光标的移动方向*/
LCD_Write(LCD_CMD,0x0c); /*开显示,关游标*/
}
//LCD 横着排列,
//横着刷新,一行一行刷
void LCD_Clear(void)
{
unsigned char i,j;
LCD_Write(LCD_CMD,0x34);
//上半部分
for(i=0;i<32;i++) //一共32行
{
LCD_Write(LCD_CMD,0x80+i); //先写入纵坐标Y的值
LCD_Write(LCD_CMD,0x80); //再写入横坐标X的值
for(j=0;j<32;j++) //一共128/8 = 16 + 16= 32列,前面16列是上半部分,后面16列是下半部分
{ //
if(j < 16)
{
LCD_Write(LCD_DAT,0x00);//0-15列
}
else
{
LCD_Write(LCD_DAT,0x00);//从16列开始,读取RAM中的32行数据
}
}
}
LCD_Write(LCD_CMD,0x36);
LCD_Write(LCD_CMD,0x30);
}
void LCD_Update(void)
{
unsigned char i,j;
LCD_Write(LCD_CMD,0x34);
//上半部分
for(i=0;i<32;i++) //一共32行
{
LCD_Write(LCD_CMD,0x80+i); //先写入纵坐标Y的值
LCD_Write(LCD_CMD,0x80); //再写入横坐标X的值
for(j=0;j<32;j++) //一共128/8 = 16 + 16= 32列,前面16列是上半部分,后面16列是下半部分
{ //
if(j < 16)
{
LCD_Write(LCD_DAT,GDRAM[i][j]);//0-15列
}
else
{
LCD_Write(LCD_DAT,GDRAM[i + 32][j - 16]);//从16列开始,读取RAM中的32行数据
}
}
}
LCD_Write(LCD_CMD,0x36);
LCD_Write(LCD_CMD,0x30);
}
uint8_t LCD_DrawDot(uint8_t x,uint8_t y,uint8_t color)//打点函数 //x,y为128*64 点阵的坐标(这个费操作,如果写到ram中,更快)
{
uint8_t row,xlabel,xlabel_bit;
uint8_t Read_H=0,Read_L=0;
LCD_Write(LCD_CMD,0x34); //扩充指令
LCD_Write(LCD_CMD,0x36); //绘图指令
xlabel=x>>4; //确定水平坐标地址
xlabel_bit=x & 0x0F; // 细分水平坐标中的第几位
if(y<32) row=y;
else { row=y-32; xlabel+=8; }
LCD_Write(LCD_CMD,row+0x80);
LCD_Write(LCD_CMD,xlabel+0x80);
LCD_Read();
Read_H=LCD_Read();
Read_L=LCD_Read();
LCD_Write(LCD_CMD,row+0x80);
LCD_Write(LCD_CMD,xlabel+0x80); //水平坐标地址+基址=显示的水平地址
if(xlabel_bit<8)
{
switch(color)
{
case 0:Read_H &=(~(0x01<<(7-xlabel_bit))); break; //变暗 ,看不见
case 1:Read_H |=(0x01<<(7-xlabel_bit)); break; //变亮 ,看得见
case 2:Read_H ^=(0x01<<(7-xlabel_bit)); break; //反转
default:break;
}
LCD_Write(LCD_DAT,Read_H);
LCD_Write(LCD_DAT,Read_L);
}
else
{
switch(color)
{
case 0:Read_L &=(~(0x01<<(15-xlabel_bit))); break; //变暗 ,看不见
case 1:Read_L |=(0x01<<(15-xlabel_bit)); break; //变亮 ,看得见
case 2:Read_L ^=(0x01<<(15-xlabel_bit)); break; //反转
default:break;
}
LCD_Write(LCD_DAT,Read_H);
LCD_Write(LCD_DAT,Read_L);
}
LCD_Write(LCD_CMD,0x30);//恢复正常模式
}
void LCD_DrawNumber(unsigned char row,unsigned char column,int number)
{
static int last_index_flag = 0;//要判断上一次是多少位,如果这一次少一个,那么就要清除前面一个位的区域,否则显示会错误
int number_byte = 0;
uint8_t minus_flag = 0;
uint8_t index_flag = 1;//至少是1位
int number_abs = 0;
if(number >= 0)
{
number_abs = number;
}
else
{
minus_flag = 1;
number_abs = -number;
}
do{
number_byte = number_abs % 10;
number_abs = number_abs / 10;
for(int i =0;i<16;i++)
{
for(int j = 0;j < 8;j++)
{
LCD_DrawDot(column + j -index_flag * 8,row + i,(font_num[number_byte][i] & (0x80 >> j))?(0x01):(0x00));
}
}
index_flag ++;
}while(number_abs);
if(minus_flag)
{
for(int i =0;i<16;i++)
{
for(int j = 0;j < 8;j++)
{
LCD_DrawDot(column + j -index_flag * 8,row + i,(font_num[10][i] & (0x80 >> j))?(0x01):(0x00));
}
}
index_flag ++;
}
if(index_flag < last_index_flag)
{
for(int i =0;i<16;i++)
{
for(int j = 0;j < 8;j++)
{
LCD_DrawDot(column + j -(index_flag) * 8,row + i,(0x00 & (0x80 >> j))?(0x01):(0x00));
}
}
}
last_index_flag = index_flag;
}
void LCD_DrawButton(unsigned char row,unsigned char column,unsigned char width,unsigned char height,unsigned char *img)
{
int index = 0;
for(int h =0;h<height;h++)
{
int count = 0;
for(int w = 0;w < width;w++)
{
LCD_DrawDot(column + w,row + h,(img[index] & (0x80 >> count))?(0x01):(0x00));
count ++;
if(count >=8)
{
index ++;
count = 0;
}
}
index ++;
}
}
void LCD_DEMO(void)
{
unsigned char str[50];
LCD_Init();
LCD_Clear();
memcpy(GDRAM,Main_UI,sizeof(Main_UI));
LCD_Update();
while(1)
{
HAL_Delay(10);
LCD_DrawNumber(10,80,ec11_count);
if(ec11_count % 2)
{
LCD_DrawButton(37,68,50,20,stop_button);
}
else
{
LCD_DrawButton(37,68,50,20,run_button);
}
//clear_lcd();
}
}