本例程使用STC32G12K128最小核心开发板,

使用的LCD显示屏:

I2C接口模式,本身提供汉字字库,可以通过和ROM有关的四个SPI接口线获取字符的点阵数据。原理图:

处理代码:
main.c
//#include "COMM/stc.h" //调用头文件
#include "stdio.h"
#include "usart2.h"
// 系统使用11.0592MHz烧录,如果修改,为了串口正常工作,要修改 Baudrate1 和 MAIN_Fosc的定义值
// 系统主频=12MHz场合,I2C的频率=800KHz,可以显示
// 系统主频=18MHz场合,I2C的频率=1.25MHz,可以显示
// 系统主频=20MHz场合,I2C的频率=1.25MHz,可以显示
// 系统主频=22MHz场合,I2C的频率=1.5MHz, 不能显示
// LCD模块的 IIC 接口引脚功能
// 1 ROM_IN LCD模块的字库数据输入
// 2 ROM_OUT LCD模块的字库点阵数据输入出
// 3 ROM_SCK LCD模块的字库访问用SCK
// 4 ROM_CS LCD模块的字库访问许可
// 5 LEDA 背光电源 背光电源正极,同 VDD 电压(5V 或 3.3V)
// 6 VSS 供电电源负极 供电电源负极
// 7 VDD 供电电源正极 供电电源正极(注意:购买时须选择 3.3V 或者是 5V 供电)
// 8 A0(RS) 寄存器选择信号 IIC 接口,悬空或接 VDD
// 9 RST 复位 低电平复位,复位完成后,回到高电平,液晶模块开始工作
// 10 CS 片选 IIC 接口,此引脚接 VSS
// 11 D7 I/0 IIC 接口,此引脚是从属地址接 VSS
// 12 D6 I/0 IIC 接口,此引脚是从属地址接 VSS
// 13 D5 I/0 IIC 接口,悬空或接 VDD
// 14 D4 I/0 IIC 接口,悬空或接 VDD
// 15-17 D3-D1(SDA) I/0 串行数据(D1、D2、D3 短接一起作为 SDA)
// 18 D0(SCK) I/0 串行时钟
// 19 RD(E) 使能信号 IIC 接口,悬空或接 VDD
// 20 WR 读/写 IIC 接口,悬空或接 VDD
sbit LCD_RST = P1^0; // RST
// 与LCD的接口,与I2C外设重合,目的是为了能使用I2C外设
sbit LCD_SCL = P1^5; // 串行时钟
sbit LCD_SDA = P1^4; // 串行数据
// 访问字库用的引脚(与SPI外设重合,目的是为后面改成SPI模式)
sbit Rom_IN = P2^3; /*字库 IC 接口定义:Rom_IN 就是字库 IC 的 SI*/
sbit Rom_OUT = P2^4; /*字库 IC 接口定义:Rom_OUT 就是字库 IC 的 SO*/
sbit Rom_SCK = P2^5; /*字库 IC 接口定义:Rom_SCK 就是字库 IC 的 SCK*/
sbit Rom_CS = P2^2; /*字库 IC 接口定义 Rom_CS 就是字库 IC 的 CS#*/
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define ADDR 0x78
#define USE_I2C_DEV 1
#define DELAY 4000000000
// 串口1用
#define Baudrate1 (65536 - MAIN_Fosc / 115200 / 4)
#define UART1_BUF_LENGTH 128
uchar TX1_Cnt; //发送计数
uchar RX1_Cnt; //接收计数
bit B_TX1_Busy; //发送忙标志
uchar RX1_Buffer[UART1_BUF_LENGTH]; //接收缓冲
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
bit TIM_10MS_Flag; //10ms的标志位
u16 Tme_CountDown = 0; //全局变量
u8 dat[32];
void sys_init(); //函数声明
void delay_ms(u16 ms); //unsigned int
void sys_init() {
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
// P3M0 = 0x00;
// P3M1 = 0x00;
// P3M0 &= ~0x03;
// P3M1 |= 0x03;
// //设置USB使用的时钟源
// IRC48MCR = 0x80; //使能内部48M高速IRC
// while (!(IRC48MCR & 0x01)); //等待时钟稳定
// USBCLK = 0x00; //使用CDC功能需要使用这两行,HID功能禁用这两行。
// USBCON = 0x90;
}
/*延时:1 毫秒的 i 倍*/
void delay_ms(unsigned long i) {
int j,k;
for(j=0;j<i;j++)
for(k=0;k<110;k++);
}
/*延时:1us 的 i 倍*/
void delay_us(unsigned long i) {
int j,k;
for(j=0;j<i;j++)
for(k=0;k<1;k++);
}
//==============================I2C外设用代码 BEGIN ==========================================
void I2C_Wait() {
while (!(I2CMSST & 0x40));
I2CMSST &= ~0x40;
}
void I2C_Start() {
I2CMSCR = 0x01; //发送START命令
I2C_Wait();
}
void I2C_SendData(char dat) {
I2CTXD = dat; //写数据到数据缓冲区
I2CMSCR = 0x02; //发送SEND命令
I2C_Wait();
}
void I2C_RecvACK() {
I2CMSCR = 0x03; //发送读ACK命令
I2C_Wait();
}
char I2C_RecvData() {
I2CMSCR = 0x04; //发送RECV命令
I2C_Wait();
return I2CRXD;
}
void I2C_SendACK() {
I2CMSST = 0x00; //设置ACK信号
I2CMSCR = 0x05; //发送ACK命令
I2C_Wait();
}
void I2C_SendNAK() {
I2CMSST = 0x01; //设置NAK信号
I2CMSCR = 0x05; //发送ACK命令
I2C_Wait();
}
void I2C_Stop()
{
I2CMSCR = 0x06; //发送STOP命令
I2C_Wait();
}
//==============================I2C外设用代码 END ==========================================
//==============================I2C模拟用代码 BEGIN ==========================================
/*START FLAG*/
void start_flag() {
LCD_SCL=1;
LCD_SDA=1; /*START FLAG*/
LCD_SDA=0; /*START FLAG*/
}
/*STOP FLAG*/
void stop_flag() {
LCD_SCL=1;
LCD_SDA=0;
LCD_SDA=1;
}
void transfer(int data1) {
int i;
for(i=0;i<8;i++) {
LCD_SCL=0;
if(data1&0x80) LCD_SDA=1;
else LCD_SDA=0;
LCD_SCL=1;
LCD_SCL=0;
data1=data1<<1;
}
LCD_SDA=0;
LCD_SCL=1;
LCD_SCL=0;
}
//写命令到液晶显示模块
void transfer_command_lcd(uchar cmd) {
#ifndef USE_I2C_DEV
start_flag();
transfer(0x78);
transfer(0x80);
transfer(cmd);
stop_flag();
#else
// ================= 单字节处理模式 ========================
I2C_Start(); //发送起始命令
I2C_SendData(ADDR); //发送设备地址+写命令
I2C_RecvACK(); // 等待ACK信号
I2C_SendData(0x80); // 指令模式
I2C_RecvACK(); // 等待ACK信号
I2C_SendData(cmd); //发送存储地址
I2C_RecvACK();
I2C_Stop(); //发送停止命令
#endif
}
//写数据到液晶显示模块
void transfer_data_lcd(uchar dat) {
#ifndef USE_I2C_DEV
// IO口模拟处理方式
start_flag();
transfer(0x78);
transfer(0xC0);
transfer(dat);
stop_flag();
#else
// ================= 单字节处理模式 ========================
I2C_Start(); //发送起始命令
I2C_SendData(ADDR); //发送设备地址+写命令
I2C_RecvACK(); // 等待ACK信号
I2C_SendData(0xC0); // 数据模式
I2C_RecvACK(); // 等待ACK信号
I2C_SendData(dat); //发送存储地址
I2C_RecvACK();
I2C_Stop(); //发送停止命令
#endif
}
//==============================I2C模拟用代码 END ==========================================
void initial_lcd() {
LCD_RST=0;
delay_ms(100);
LCD_RST=1;
delay_ms (100);
transfer_command_lcd(0x30); //EXT=0
transfer_command_lcd(0x94); //Sleep out
transfer_command_lcd(0x31); //EXT=1
transfer_command_lcd(0xD7); //Autoread disable
transfer_data_lcd(0X9F); //
transfer_command_lcd(0x32); //Analog SET
transfer_data_lcd(0x00); //OSC Frequency adjustment
transfer_data_lcd(0x01); //Frequency on booster capacitors->6KHz
transfer_data_lcd(0x03); //Bias=1/11
transfer_command_lcd(0x20); // Gray Level
transfer_data_lcd(0x01);
transfer_data_lcd(0x03);
transfer_data_lcd(0x05);
transfer_data_lcd(0x07);
transfer_data_lcd(0x09);
transfer_data_lcd(0x0b);
transfer_data_lcd(0x0d);
transfer_data_lcd(0x10);
transfer_data_lcd(0x11);
transfer_data_lcd(0x13);
transfer_data_lcd(0x15);
transfer_data_lcd(0x17);
transfer_command_lcd(0x31); //Analog SET
transfer_command_lcd(0xf2); //温度补偿
transfer_data_lcd(0x1e); //OSC Frequency adjustment
transfer_data_lcd(0x28); //Frequency on booster capacitors->6KHz
transfer_data_lcd(0x32); //
transfer_data_lcd(0x00);
transfer_data_lcd(0x01);
transfer_data_lcd(0x03);
transfer_command_lcd(0x30); //EXT=0
transfer_command_lcd(0x75); //Page Address setting
transfer_data_lcd(0X00); // XS=0
transfer_data_lcd(0X14); // XE=159 0x28
transfer_command_lcd(0x15); //Clumn Address setting
transfer_data_lcd(0X00); // XS=0
transfer_data_lcd(0Xff); // XE=256
transfer_command_lcd(0xBC); //Data scan direction
transfer_data_lcd(0x00); //MX.MY=Normal
transfer_data_lcd(0xA6);
transfer_command_lcd(0xCA); //Display Control
transfer_data_lcd(0X00); //
transfer_data_lcd(0X9F); //Duty=160
transfer_data_lcd(0X20); //Nline=off
transfer_command_lcd(0xF0); //Display Mode
transfer_data_lcd(0X10); //10=Monochrome Mode,11=4Gray
transfer_command_lcd(0x81); //EV control
transfer_data_lcd(0x0a); //VPR[5-0] //可设置范围 0x00~0x3f,每格电压是 0.04V
transfer_data_lcd(0x04); //VPR[8-6] //可设置范围 0x00~0x07
transfer_command_lcd(0x20); //Power control
transfer_data_lcd(0x0B); //D0=regulator ; D1=follower ; D3=booste, on:1 off:0
delay_us(100);
transfer_command_lcd(0xAF); //Display on
}
/*写 LCD 行列地址:X 为起始的列地址,Y 为起始的行地址,x_total,y_total 分别为列地址及行地址的起点到终点的差值 */
void lcd_address(int x,int y,x_total,y_total) {
x=x-1;
y=y+7;
transfer_command_lcd(0x15); //Set Column Address
transfer_data_lcd(x);
transfer_data_lcd(x+x_total-1);
transfer_command_lcd(0x75); //Set Page Address
transfer_data_lcd(y);
transfer_data_lcd(y+y_total-1);
transfer_command_lcd(0x30);
transfer_command_lcd(0x5c);
}
/*清屏*/
void clear_screen() {
int i,j;
lcd_address(1,1,256,17);
for(i=0;i<17;i++) {
for(j=0;j<256;j++) {
transfer_data_lcd(0x00);
}
}
}
/****送指令到晶联讯字库 IC***/
void send_command_to_ROM( uchar datu ) {
uchar i;
for(i=0;i<8;i++ ) {
if(datu&0x80)
Rom_IN = 1;
else
Rom_IN = 0;
datu = datu<<1;
Rom_SCK=0;
Rom_SCK=1;
delay_us(1);
}
}
/****从晶联讯字库 IC 中取汉字或字符数据(1 个字节)***/
static uchar get_data_from_ROM(void) {
uchar i;
uchar ret_data=0;
Rom_SCK=1;
for(i=0;i<8;i++) {
Rom_OUT=1;
Rom_SCK=0;
ret_data>>=1;
if( Rom_OUT )
ret_data+=0x80;
else
ret_data=ret_data+0;
Rom_SCK=1;
delay_us(1);
}
return(ret_data);
}
//从指定地址读出数据写到液晶屏指定(page,column)座标中
void get_and_write_8x16(ulong fontaddr, uchar column, uchar page) {
uchar i,j,disp_data;
Rom_CS = 0;
send_command_to_ROM(0x03);
send_command_to_ROM((fontaddr&0xff0000)>>16); //地址的高 8 位,共 24 位
send_command_to_ROM((fontaddr&0xff00)>>8); //地址的中 8 位,共 24 位
send_command_to_ROM(fontaddr&0xff); //地址的低 8 位,共 24 位
lcd_address(column,page,8,2);
for(j=0;j<2;j++) {
for(i=0; i<8; i++ ) {
disp_data=get_data_from_ROM();
transfer_data_lcd(disp_data); //写数据到 LCD,每写完 1 字节的数据后列地址自动加 1
}
}
Rom_CS=1;
}
void get_and_write_12x24(ulong fontaddr, uchar column, uchar page) {
uchar i,j,disp_data;
Rom_CS = 0;
send_command_to_ROM(0x03);
send_command_to_ROM((fontaddr&0xff0000)>>16); //地址的高 8 位,共 24 位
send_command_to_ROM((fontaddr&0xff00)>>8); //地址的中 8 位,共 24 位
send_command_to_ROM(fontaddr&0xff); //地址的低 8 位,共 24 位
lcd_address(column,page,16,3);
for(j=0;j<3;j++) {
for(i=0; i<16; i++ ) {
disp_data=get_data_from_ROM();
transfer_data_lcd(disp_data); //写数据到 LCD,每写完 1 字节的数据后列地址自动加 1
}
}
Rom_CS=1;
}
void get_and_write_16x32(ulong fontaddr, uchar column, uchar page) {
uchar i,j,disp_data;
Rom_CS = 0;
send_command_to_ROM(0x03);
send_command_to_ROM((fontaddr&0xff0000)>>16); //地址的高 8 位,共 24 位
send_command_to_ROM((fontaddr&0xff00)>>8); //地址的中 8 位,共 24 位
send_command_to_ROM(fontaddr&0xff); //地址的低 8 位,共 24 位
lcd_address(column,page,16,4);
for(j=0;j<4;j++) {
for(i=0; i<16; i++ ) {
disp_data=get_data_from_ROM();
transfer_data_lcd(disp_data); //写数据到 LCD,每写完 1 字节的数据后列地址自动加 1
}
}
Rom_CS=1;
}
//从指定地址读出数据写到液晶屏指定(page,column)座标中
void get_and_write_16x16(ulong fontaddr, uchar column, uchar page) {
uchar i,j,disp_data;
Rom_CS = 0;
send_command_to_ROM(0x03);
send_command_to_ROM((fontaddr&0xff0000)>>16); //地址的高 8 位,共 24 位
send_command_to_ROM((fontaddr&0xff00)>>8); //地址的中 8 位,共 24 位
send_command_to_ROM(fontaddr&0xff); //地址的低 8 位,共 24 位
lcd_address(column,page,16,2);
for(j=0;j<2;j++) {
for(i=0; i<16; i++ ) {
disp_data=get_data_from_ROM();
transfer_data_lcd(disp_data); //写数据到 LCD,每写完 1 字节的数据后列地址自动加 1
}
}
Rom_CS=1;
}
//从指定地址读出数据写到液晶屏指定(page,column)座标中
void get_and_write_24x24(ulong fontaddr, uchar column, uchar page) {
uchar i,j,disp_data;
Rom_CS = 0;
send_command_to_ROM(0x03);
send_command_to_ROM((fontaddr&0xff0000)>>16); //地址的高 8 位,共 24 位
send_command_to_ROM((fontaddr&0xff00)>>8); //地址的中 8 位,共 24 位
send_command_to_ROM(fontaddr&0xff); //地址的低 8 位,共 24 位
lcd_address(column,page,24,3);
for(j=0;j<3;j++) {
for(i=0; i<24; i++ ) {
disp_data=get_data_from_ROM();
transfer_data_lcd(disp_data); //写数据到 LCD,每写完 1 字节的数据后列地址自动加 1
}
}
Rom_CS=1;
}
//从指定地址读出数据写到液晶屏指定(page,column)座标中
void get_and_write_32x32(ulong fontaddr,uchar column, uchar page) {
uchar i,j,disp_data;
Rom_CS = 0;
send_command_to_ROM(0x03);
send_command_to_ROM((fontaddr&0xff0000)>>16); //地址的高 8 位,共 24 位
send_command_to_ROM((fontaddr&0xff00)>>8); //地址的中 8 位,共 24 位
send_command_to_ROM(fontaddr&0xff); //地址的低 8 位,共 24 位
lcd_address(column,page,32,4);
for(j=0;j<4;j++) {
for(i=0; i<32; i++ ) {
disp_data=get_data_from_ROM();
transfer_data_lcd(disp_data); //写数据到 LCD,每写完 1 字节的数据后列地址自动加 1
}
}
Rom_CS=1;
}
//****************************************************************
ulong fontaddr=0;
void display_GB2312_16x16_string(uchar column, uchar page, uchar *text) {
uchar i= 0;uint temp1,temp2;
temp1=column;
temp2=page;
while((text[i]>0x00)) {
if(((text[i]>=0xb0) &&(text[i]<=0xf7))&&(text[i+1]>=0xa1)) {
//国标简体(GB2312)汉字在晶联讯字库 IC 中的地址由以下公式来计算:
//Address = ((MSB - 0xB0) * 94 + (LSB - 0xA1)+ 846)*32+ BaseAdd;BaseAdd=0
//由于担心 8 位单片机有乘法溢出问题,所以分三部取地址
fontaddr = (text[i]- 0xb0)*94;
fontaddr += (text[i+1]-0xa1)+846;
fontaddr = (ulong)(fontaddr*32);
fontaddr = (ulong)(fontaddr+0x2c9d0);
get_and_write_16x16(fontaddr,column,page); //从指定地址读出数据写到液晶屏指定(page,column)座标中
i+=2;
column+=16;
if ((temp2<=15&&temp1<=256)&&column>248) {
//自动换行,当遇到奇数个字母或符号就提前 8 个点
//设成符>256 时当有奇数个字符时就会显半个汉字,因为一个字符只占 8 个点(一个字节)
column=1;
page+=2;
if (page>15)column=1;
}
} else if(((text[i]>=0xa1) &&(text[i]<=0xa3))&&(text[i+1]>=0xa1)) {
//国标简体(GB2312)15x16 点的字符在晶联讯字库 IC 中的地址由以下公式来计算:
//Address = ((MSB - 0xa1) * 94 + (LSB - 0xA1))*32+ BaseAdd;BaseAdd=0
//由于担心 8 位单片机有乘法溢出问题,所以分三部取地址
fontaddr = (text[i]- 0xa1)*94;
fontaddr += (text[i+1]-0xa1);
fontaddr = (ulong)(fontaddr*32);
fontaddr = (ulong)(fontaddr+0x2c9d0);
get_and_write_16x16(fontaddr,column,page); //从指定地址读出数据写到液晶屏指定(page,column)座标中
i+=2;
column+=16;
if ((temp2<=15&&temp1<=256)&&column>248) {
//自动换行,当遇到奇数个字母或符号就提前 8 个点
//设成符>128 时当有奇数个字符时就会显半个汉字,因为一个字符只占 8 个点(一个字节)
column=1;
page+=2;
if (page>15)column=1;
}
} else if((text[i]>=0x20) &&(text[i]<=0x7e)) {
fontaddr = (text[i]- 0x20);
fontaddr = (unsigned long)(fontaddr*16);
fontaddr = (unsigned long)(fontaddr+0x1dd780);
get_and_write_8x16(fontaddr,column,page); //从指定地址读出数据写到液晶屏指定(page,column)座标中
i+=1;
column+=8;
if ((temp1<=15&&temp2<=256)&&column>248) {
//自动换行,当遇到奇数个字母或符号就提前 8 个点
//设成符>128 时当有奇数个字符时就会显半个汉字,因为一个字符只占 8 个点(一个字节)
column=1;
page+=2;
if (page>15)column=1;
}
} else {
i++;
}
}
}
//****************************************************************
void display_GB2312_24x24_string(uchar column,uchar page,uchar *text) {
uchar i= 0;uint temp1,temp2;
temp1=column;
temp2=page;
while((text[i]>0x00)) {
if(((text[i]>=0xb0) &&(text[i]<=0xf7))&&(text[i+1]>=0xa1)) {
//国标简体(GB2312)汉字在晶联讯字库 IC 中的地址由以下公式来计算:
//Address = ((MSB - 0xB0) * 94 + (LSB - 0xA1)+ 846)*32+ BaseAdd;BaseAdd=0
//由于担心 8 位单片机有乘法溢出问题,所以分三部取地址
fontaddr = (text[i]- 0xb0)*94;
fontaddr += (text[i+1]-0xa1)+846;
fontaddr = (ulong)(fontaddr*72);
fontaddr = (ulong)(fontaddr+0X068190);
get_and_write_24x24(fontaddr,column,page); //从指定地址读出数据写到液晶屏指定(page,column)座标中
i+=2;
column+=24;
} else if(((text[i]>=0xa1) &&(text[i]<=0xa9))&&(text[i+1]>=0xa1)) {
//国标简体(GB2312)15x16 点的字符在晶联讯字库 IC 中的地址由以下公式来计算:
//Address = ((MSB - 0xa1) * 94 + (LSB - 0xA1))*32+ BaseAdd;BaseAdd=0
//由于担心 8 位单片机有乘法溢出问题,所以分三部取地址
fontaddr = (text[i]- 0xa1)*94;
fontaddr += (text[i+1]-0xa1);
fontaddr = (ulong)(fontaddr*72);
fontaddr = (ulong)(fontaddr+0X068190);
get_and_write_24x24(fontaddr,column,page); //从指定地址读出数据写到液晶屏指定(page,column)座标中
i+=2;
column+=24;
} else if((text[i]>=0x20) &&(text[i]<=0x7e)) {
fontaddr = (text[i]- 0x20);
fontaddr = (unsigned long)(fontaddr*48);
fontaddr = (unsigned long)(fontaddr+0x1dff00);
get_and_write_12x24(fontaddr,column,page); //从指定地址读出数据写到液晶屏指定(page,column)座标中
i+=1;
column+=12;
} else {
i++;
}
}
}
//****************************************************************
void display_GB2312_32x32_string(uchar column,uchar page,uchar *text) {
uchar i= 0;uint temp1,temp2;
temp1=column;
temp2=page;
while((text[i]>0x00)) {
if(((text[i]>=0xb0) &&(text[i]<=0xf7))&&(text[i+1]>=0xa1)) {
//国标简体(GB2312)汉字在晶联讯字库 IC 中的地址由以下公式来计算:
//Address = ((MSB - 0xB0) * 94 + (LSB - 0xA1)+ 846)*32+ BaseAdd;BaseAdd=0
//由于担心 8 位单片机有乘法溢出问题,所以分三部取地址
fontaddr = (text[i]- 0xb0)*94;
fontaddr += (text[i+1]-0xa1)+846;
fontaddr = (ulong)(fontaddr*128);
fontaddr = (ulong)(fontaddr+0xedf00);
get_and_write_32x32(fontaddr,column,page); //从指定地址读出数据写到液晶屏指定(page,column)座标中
i+=2;
column+=32;
} else if(((text[i]>=0xa1) &&(text[i]<=0xa9))&&(text[i+1]>=0xa1)) {
//国标简体(GB2312)15x16 点的字符在晶联讯字库 IC 中的地址由以下公式来计算:
//Address = ((MSB - 0xa1) * 94 + (LSB - 0xA1))*32+ BaseAdd;BaseAdd=0
//由于担心 8 位单片机有乘法溢出问题,所以分三部取地址
fontaddr = (text[i]- 0xa1)*94;
fontaddr += (text[i+1]-0xa1);
fontaddr = (ulong)(fontaddr*128);
fontaddr = (ulong)(fontaddr+0xedf00);
get_and_write_32x32(fontaddr,column,page); //从指定地址读出数据写到液晶屏指定(page,column)座标中
i+=2;
column+=32;
} else if((text[i]>=0x20) &&(text[i]<=0x7e)) {
fontaddr = (text[i]- 0x20);
fontaddr = (unsigned long)(fontaddr*64);
fontaddr = (unsigned long)(fontaddr+0x1e5a50);
get_and_write_16x32(fontaddr,column,page); //从指定地址读出数据写到液晶屏指定(page,column)座标中
i+=1;
column+=16;
} else {
i++;
}
}
}
/*显示 256*96 点阵的图像*/
void disp_256x96(int x,int y,char *dp) {
int i,j;
lcd_address(x,y,256,12);
for(i=0;i<12;i++) {
for(j=0;j<256;j++) {
transfer_data_lcd(*dp);
dp++;
}
}
}
// 串口1:P3.0,P3.1
// ==================================== 串口1 BEGIN =======================================
//========================================================================
// 函数: void PrintString1(u8 *puts)
// 描述: 串口1发送字符串函数。
// 参数: puts: 字符串指针.
//========================================================================
void PrintString1(uchar *puts)
{
for (; *puts != 0; puts++) //遇到停止符0结束
{
SBUF = *puts;
B_TX1_Busy = 1;
while(B_TX1_Busy);
}
}
//========================================================================
// 函数: void UART1_config(u8 brt)
// 描述: UART1初始化函数。
// 参数: brt: 选择波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
//========================================================================
void UART1_config(uchar brt)
{
/*********** 波特率使用定时器2 *****************/
if(brt == 2) {
S1BRT = 1; //S1 BRT Use Timer2;
SetTimer2Baudraye(Baudrate1);
}
/*********** 波特率使用定时器1 *****************/
else {
TR1 = 0;
S1BRT = 0; //S1 BRT Use Timer1;
T1_CT = 0; //Timer1 set As Timer
T1x12 = 1; //Timer1 set as 1T mode
TMOD &= ~0x30;//Timer1_16bitAutoReload;
TH1 = (u8)(Baudrate1 / 256);
TL1 = (u8)(Baudrate1 % 256);
ET1 = 0; //禁止中断
TR1 = 1;
}
/*************************************************/
SCON = (SCON & 0x3f) | 0x40; //UART1模式, 0x00: 同步移位输出, 0x40: 8位数据,可变波特率, 0x80: 9位数据,固定波特率, 0xc0: 9位数据,可变波特率
// PS = 1; //高优先级中断
ES = 1; //允许中断
REN = 1; //允许接收
P_SW1 &= 0x3f;
// P_SW1 |= 0x00; //UART1 switch to, 0x00: P3.0 P3.1, 0x40: P3.6 P3.7, 0x80: P1.6 P1.7, 0xC0: P4.3 P4.4
B_TX1_Busy = 0;
TX1_Cnt = 0;
RX1_Cnt = 0;
}
//========================================================================
// 函数: void UART1_int (void) interrupt UART1_VECTOR
// 描述: UART1中断函数。
//========================================================================
void UART1_int (void) interrupt 4 {
if(RI) {
RI = 0;
RX1_Buffer[RX1_Cnt] = SBUF;
if(++RX1_Cnt >= UART1_BUF_LENGTH) RX1_Cnt = 0;
}
if(TI) {
TI = 0;
B_TX1_Busy = 0;
}
}
// ==================================== 串口1 END =======================================
void main() {
u8 i;
char str[30];
int temp=0;
sys_init(); // IO口初始化
UART1_config(2); // 选择波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
UART2_config(2); // 选择波特率, 2: 使用Timer2做波特率, 其它值: 无效.
#ifdef USE_I2C_DEV
// I2C 外设初始化
I2C_S1 =0; I2C_S0 =0; //I2C功能脚选择,00:P1.5,P1.4; 01:P2.5,P2.4; 11:P3.2,P3.3
I2CCFG = 0xe0; //使能I2C主机模式
I2CMSST = 0x00;
#endif
EA = 1; // CPU开放中断,打开总中断。
PrintString1("STC32G UART1 Test Programme!\r\n"); //UART1发送一个字符串
PrintString2("STC32G UART2 Test Programme!\r\n"); //UART2发送一个字符串
initial_lcd(); //对液晶模块进行初始化设置
clear_screen();
display_GB2312_16x16_string(1,1,"ABC123");
display_GB2312_16x16_string(1,3,"abc01234");
display_GB2312_16x16_string(1,5,"简体汉字 8X16、12X24、16X32");
while(1) {
}
}uart2.c
#include "usart2.h"
u8 TX2_Cnt; //发送计数
u8 RX2_Cnt; //接收计数
bit B_TX2_Busy; //发送忙标志
u8 RX2_Buffer[UART2_BUF_LENGTH]; //接收缓冲
bit Rec_Flag = 0; //接受完成标志位
//========================================================================
// 函数: void UART2_config(u8 brt)
// 描述: UART2初始化函数。
// 参数: brt: 选择波特率, 2: 使用Timer2做波特率, 其它值: 无效.
// 备注: 使用Timer2做波特率 : 115200
//========================================================================
void UART2_config(u8 brt) {
if(brt == 2) {
SetTimer2Baudraye(Baudrate2);
S2CFG |= 0x01; //使用串口2时,W1位必需设置为1,否则可能会产生不可预期的错误
S2CON = (S2CON & 0x3f) | 0x40; //UART2模式, 0x00: 同步移位输出, 0x40: 8位数据,可变波特率, 0x80: 9位数据,固定波特率, 0xc0: 9位数据,可变波特率
ES2 = 1; //允许中断
S2REN = 1; //允许接收
S2_S = 1; //UART2 switch to: 0: P1.0 P1.1, 1: P4.6 P4.7
B_TX2_Busy = 0;
TX2_Cnt = 0;
RX2_Cnt = 0;
}
}
//========================================================================
// 函数: SetTimer2Baudraye(u32 dat)
// 描述: 设置Timer2做波特率发生器。
// 参数: dat: Timer2的重装值.
=================================================================
void SetTimer2Baudraye(u32 dat) {
T2R = 0; //Timer stop
T2_CT = 0; //Timer2 set As Timer
T2x12 = 1; //Timer2 set as 1T mode
T2H = (u8)(dat / 256);
T2L = (u8)(dat % 256);
ET2 = 0; //禁止中断
T2R = 1; //Timer run enable
}
//========================================================================
// 函数: void UART2_int (void) interrupt UART2_VECTOR
// 描述: UART2中断函数。
//========================================================================
void UART2_int (void) interrupt 8 {
// 如果接受到数据
if(S2RI) {
S2RI = 0; //Clear Rx flag
RX2_Buffer[RX2_Cnt] = S2BUF;
if( RX2_Buffer[RX2_Cnt]== '\n' ) {
if( RX2_Buffer[RX2_Cnt-1]== '\r' ) {
Rec_Flag = 1;
}
RX2_Cnt = 0;
} else {
RX2_Cnt++;
}
}
if(S2TI) {
S2TI = 0; //Clear Tx flag
B_TX2_Busy = 0;
}
}
//========================================================================
// 函数: void PrintString2(u8 *puts)
// 描述: 串口2发送字符串函数。
// 参数: puts: 字符串指针.
//========================================================================
void PrintString2(u8 *puts) {
// 遇到停止符0结束
for (; *puts != 0; puts++) {
S2BUF = *puts;
B_TX2_Busy = 1;
while(B_TX2_Busy);
}
}串口1对应于开发板上的串口,串口2使用 P4.7 和 P4.6 。
程序运行效果:

我要赚赏金
