📄 st7920.txt
字号:
12864 keil的,串行方式 编写时已经考虑到往avr上的移植了,spi可以用avr硬件的,也可以用io模拟,甚至可以用mega48的串口做spi主机
,经过我的测试串行方式,在cs无效时,7920还是可以接受数据,导致显示被误改,如果spi上接了其它器件,小心使用。
sbit ST7920CS=P3^3;
void write7920cmd(unsigned char cmd)
{
unsigned char i=0;
ST7920CS=1;
Spi(0xf8);
Spi(cmd&0xf0);
Spi(cmd<<4);
ST7920CS=0;
Delay10us(10);
}
void write7920data(unsigned char dat)
{
ST7920CS=1;
Spi(0xfa);
Spi(dat&0xf0);
Spi(dat<<4);
ST7920CS=0;
Delay10us(10);
}
void init7920(void)
{
write7920cmd(0x20);//4bit 基本指令
write7920cmd(0x20);//4bit 基本指令
write7920cmd(0x0c);//开显示
write7920cmd(0x01);//清屏
write7920cmd(0x06);
}
void DispSetCursor(unsigned char LineNum, unsigned char ColumnNum)
{
unsigned char i=0x00;
switch(LineNum&0x0f) //确定行号
{
case 0x00:
i=0x80;
break;
case 0x01:
i=0x90;
break;
case 0x02:
i=0x88;
break;
case 0x03:
i=0x98;
break;
default :
break;
}
i = (ColumnNum&0x0f)|i; //确定列号
write7920cmd(i);
}
汉字显示参考代码
unsigned char code mainmenu[]="1:当前时间2:tcp/ip参数设置3:AD采样按 1,2,3选择操作";
void dis_mainmenu(void)
{
unsigned char i;
DispSetCursor(0,0); //
for (i=0;i<10;i++) //
{
write7920data(mainmenu[i]); //1:当前时间
}
DispSetCursor(1,0); //
for (;i<26;i++) //
{
write7920data(mainmenu[i]); //2:tcp/ip参数设置
}
DispSetCursor(2,0); //
for (;i<34;i++) //
{
write7920data(mainmenu[i]); //3:AD采样
}
DispSetCursor(3,0); //
for (;i<50;i++) //
{
write7920data(mainmenu[i]); //按 1,2,3选择操作
}
}
谢谢mucode...
我也将51asm移植到WinAvr,但由于买的是5V的HS12232-9,但手头只有3.3V的M8L系统,所以驱动不了,不知对否???
山区确实山路崎岖,3.3V的HS12232-9必须一周后才能到货...
只好明天上班用5V系统了...
以下是我移植的,请mucode同志个指教一番...主要是在时序方面...
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/wdt.h>
#include <avr/ina90.h>
#include <avr/eeprom.h>
//#include <stdio.h>
#include <avr/delay.h>
#define FREQ 8 //Meaga8L,8MHz
#define CS PB2//LCD片选(串行) 0:禁止 1:允许
#define SID PB3//LCD输入串行数据(串行)
#define CLK PB5//LCD输入串行脉冲(串行)
#define SS PB2//LCD片选(串行) 0:禁止 1:允许
#define MOSI PB3//LCD输入串行数据(串行)
#define SCK PB5//LCD输入串行脉冲(串行)
void PortIoInit(void)
{
DDRB = 0;//设置B口全为输入
DDRC = 0;//设置C口全为输入
DDRD = 0;//设置D口全为输入
PORTB = 0xff;//设置B口全部上拉
PORTC = 0xff;//设置C口全部上拉
PORTD = 0xff;//设置D口全部上拉
}
void SPI_MasterInit(void)
{
/* 设置MOSI 和SCK 为输出,其他为输入 */
DDRB = (1 << MOSI) | (1 << SCK);
/* 使能SPI 主机模式,设置时钟速率为fck/16 ,SPI方式3*/
SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPOL) | (1 << CPHA) | (1 << SPR0);
/* 使能SPI 主机模式,设置时钟速率为fck/16 ,SPI方式2*/
// SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPOL) | (1 << SPR0);
}
void SPI_MasterTransmit(unsigned char cData)
{
/* 启动数据传输 */
SPDR = cData;
/* 等待传输结束 */
while(!(SPSR & (1 << SPIF)));
}
void DelayMs(unsigned int t)
{
unsigned int i;
for(i = 0; i < t; i++)
_delay_loop_2(250 * FREQ);
}
/*--------------------------------------------------------
发送8位LCD控制命令
--------------------------------------------------------*/
void LcdSendCommand(unsigned char cCommand)
{
_delay_loop_2(72 * FREQ);//st7920要求等待72uS
/*--------------------------------------------------------
发送同步脉冲11111 WR(0) RS(0) 0发送顺序从左至右)
--------------------------------------------------------*/
PORTB &= ~(1 << SS);//SS=0,启动SPI
SPI_MasterTransmit(0xf8);//发送LCD控制命令
SPI_MasterTransmit(cCommand & 0xf0);//发送高4位LCD控制命令
SPI_MasterTransmit(cCommand << 4);//发送低4位LCD控制命令
PORTB |= (1 << SS);//SS=1,关闭SPI
}
/*--------------------------------------------------------
发送8位LCD显示数据
--------------------------------------------------------*/
void LcdSendData(unsigned char cData)
{
_delay_loop_2(72 * FREQ);//st7920要求等待延时72uS
/*--------------------------------------------------------
发送同步脉冲11111 WR(0) RS(0) 0发送顺序从左至右)
--------------------------------------------------------*/
PORTB &= ~(1 << SS);//SS=0,启动SPI
SPI_MasterTransmit(0xfa);//发送LCD显示数据
SPI_MasterTransmit(cData & 0xf0);//发送高4位LCD显示数据
SPI_MasterTransmit(cData << 4);//发送低4位LCD显示数据
PORTB |= (1 << SS);//SS=1,关闭SPI
}
/*---------------------------------------------------
LCD初始化设置
----------------------------------------------------*/
void LcdInit(void)
{
/*---------------------------------------------------
LCD模块上电等待延时
----------------------------------------------------*/
DelayMs(1000);//上电等待延时1000Ms
SPI_MasterInit();//SPI初始化
LcdSendCommand(0b00100000);//发送4位控制命令
LcdSendCommand(0b00000010);//发送位址归位命令,设定DDRAM位址计数器为0
LcdSendCommand(0b00000100);//发送进入点命令
LcdSendCommand(0b00001100);//发送开显示关光标命令
LcdSendCommand(0b00000001);//发送清除显示命令
LcdSendCommand(0b10000000);//发送设定DDRAM地址0x00命令
}
unsigned char SetLcdDisplayCharPos(unsigned char row, unsigned char col)
{
if ((row < 2) && (col < 16))//英文字符为2行16列
{
LcdSendCommand(0x80 + row * 16 + col);//发送设定DDRAM地址row * 16 + col命令
return 1;
}
else
return 0;
}
void LcdDisplayChar(unsigned char row, unsigned char col, unsigned char * string)
{
if (SetLcdDisplayCharPos(row, col))
{
LcdSendData(*string);
}
}
unsigned char SetLcdDisplayChinsePos(unsigned char row, unsigned char col)
{
if ((row < 2) && (col < 8))//汉字字符为2行8列(偶数对齐)
{
LcdSendCommand(0x80 + row * 16 + col * 2);//发送设定DDRAM地址row * 16 + col * 2命令
return 1;
}
else
return 0;
}
void LcdDisplayChinse(unsigned char row, unsigned char col, unsigned char * string)
{
if (SetLcdDisplayChinsePos(row, col))
{
LcdSendData(*string);
LcdSendData(*(string + 1));
}
}
void LcdDisplayString(unsigned char * string)
{
while(*string) LcdSendData(*string ++);
}
//main程序
void main(void)
{
PortIoInit();
LcdInit();
// sei();
SetLcdDisplayChinsePos(0, 0);//汉字定位到上行左端
LcdDisplayString("汉字显示演示程序");
SetLcdDisplayCharPos(1,0);//字符定位到下行左端
LcdDisplayString("0123456789ABCDEF");
for(;;)
{
}
}
用串行方式的最大缺点:无法读取显示ram
复杂的图形操作可能就不好做了
另外我用的这个12864,和一个spi的ad挂在一起,用两个io分别使能,结果ad控制正常,st7920却不受cs控制,始终接受数据,导致控制ad时显示乱码。现在pcb不能改,只好想办法破坏时序,避免显示出错。
我正好写过一个,不过是4位的。
//********************************************
//7920中文LCD屏,带中文字库
//联接: LCD MEGA128
// RS ----- PORTC.0
// RD ----- PORTC.1
// EN ----- PORTC.2
// DB4 ----- PORTC.4
// DB5 ----- PORTC.5
// DB6 ----- PORTC.6
// DB7 ----- PORTC.7
//********************************************
#define LCD_RS PORTC.0
#define LCD_RD PORTC.1
#define LCD_EN PORTC.2
#define LCD_DB PORTC
//********************************************
//将数据输出到LCD接口,LCD数据口宽度为4bit
//rs: 1 操作指令寄存器,0 操作数据寄存器
//rd: 1 从LCD读出数据, 0 向LCD写数据
//db: 要写入的数据,仅底4位有效
//********************************************
void lcd_setport(char rs,char rd,char db)
{
//unsigned char temp;
db=db<<4;
LCD_RS=rs;
LCD_RD=rd;
delay_us(20);
LCD_EN=1;
delay_us(10);
LCD_DB=LCD_DB&0x0F;
LCD_DB=LCD_DB|db;
//LCD_DB=db;
delay_us(10);
LCD_EN=0;
delay_us(20);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -