用STC32G12K128驱动320240LCD,RA8806芯片,总是有雪花点,还会死机
下面是RA8806的驱动,奇怪的是 Readreg()函数,RA8806按说明,BRD=0 应该放在dat = DATA_BUS;前面可是就没有图像显示,放在后面却显示图像了
//== RA8806.c ===========================================================
#include "STC32G.h"
#include "delay.h"
#include "stdio.h"
#include "intrins.h"
#include "RA8806.h"
#include "NtGUI.h"
extern void delay_ms(unsigned int MS);
//写命令
//写完命令后片选仍为0!BRS仍保留状态!而BWR回复到1!
//在执行完此函数后,可以:
//1.后跟LCD_DataWrite(unsigned char DataByte),BRS=0,BWR=0>>1,写DataByt到CommandByte(reg#)。
//2.后跟LCD_DataRea(),BRS=0,BRD=0>>1,读CommandByte(reg#)中的数据。
void LCD_CmdWrite(unsigned char CommandByte)
{
BRD = 1;
BCS = 0; //写完命令后片选仍为0!
BRS = 1; //寄存器操作
BWR = 0;
DATA_BUS = CommandByte;
delay_us(2);
BWR = 1;
DATA_BUS = 0xff;
BCS = 1;
}
//写数据
void LCD_DataWrite(unsigned char DataByte)
{
BRS = 0; //数据操作
BCS = 0;
BWR = 0;
DATA_BUS = DataByte;
delay_us(2);
BWR = 1;
BCS = 1;
DATA_BUS = 0xff;
}
//读寄存器数据
unsigned char LCD_DataRead(void)
{
unsigned char dat;
BRS = 0; //对寄存器操作
BCS = 0;
DATA_BUS = 0xff; //数据端口应为开漏加上拉电阻
BRD = 0;
dat = DATA_BUS;
//BRD = 0; //源程序此句在dat = DATA_BUS;上面
delay_us(2);
BRD = 1;
BCS = 1;
return dat;
}
//写指令: LCD_CmdWrite(CmdByte) & LCD_DataWrite(DataByte) 组合
void WriteCommand(unsigned char CommandReg,unsigned char CommandByte)
{
BRD = 1;
BRS = 1; //寄存器操作
BCS = 0;
BWR = 0;
DATA_BUS = CommandReg;
delay_us(2);
BWR = 1;
BRS = 0; //数据操作
BWR = 0;
DATA_BUS = CommandByte;
delay_us(2);
BWR = 1;
BCS = 1;
DATA_BUS = 0xff;
}
//LCD_CmdWrite(CmdByte) & LCD_DataRead()组合
//读寄存器:
unsigned char Readreg(unsigned char CommandReg)
{
unsigned char dat;
BCS = 0; //CS=0
BRS = 1; //寄存器操作-指定寄存器
BWR = 0;
DATA_BUS = CommandReg;
BWR = 1;
BCS = 1;
delay_us(15);
BRS = 0; //读出寄存器的内容
BCS = 0;
DATA_BUS = 0xff;
//BRD = 0;
dat = DATA_BUS;
BRD = 0; //源程序此句应该在dat = DATA_BUS前面
BRD = 1;
BCS = 1; //CS=1
return dat;
}
//等于LCD_CmdRead()
unsigned char Read_status(void)
{
unsigned char dat;
BWR = 1;
BRS = 1; //对寄存器操作,但此时不会去读CommandByte内的数据,而是去读ststus
BCS = 0;
DATA_BUS = 0xff; //数据端口应为开漏加上拉电阻
BRD = 0;
dat = DATA_BUS;
delay_us(2);
BRD = 1;
BCS = 1;
return dat;
}
//读内存,此命令是应跟在写命令B1后面,连续读内存,用到结束应将CS=1
unsigned char LCD_DDRamRead(void)
{
unsigned char dat;
BRS = 1; //对寄存器操作
BCS = 0;
DATA_BUS = 0xff; //数据端口应为开漏加上拉电阻
BRD = 0;
dat = DATA_BUS;
BRD = 1;
return dat; //
}
//读命令数据
unsigned char LCD_CmdRead(void)
{
unsigned char dat;
BRS = 1; //对寄存器操作
BCS = 0;
DATA_BUS = 0xff; //数据端口应为开漏加上拉电阻
BRD = 0;
dat = DATA_BUS;
delay_us(1);
BRD = 1;
BCS = 1;
return dat; //
}
void CheckBusy(void)
{
unsigned char temp;
do
{
temp=LCD_DataRead();
}
while(temp & 0x80);
}
void LCD_Graphic(void)
{
unsigned char temp;
temp = Readreg(0x00);
temp &= 0xf7;
WriteCommand(0x00,temp);
// unsigned char temp;
// //No_Snow_Mode();
// LCD_CmdWrite(0x00);
// temp = LCD_DataRead();
// temp &= cClrb3;
// LCD_CmdWrite(0x00);
// LCD_DataWrite(temp); //如果LCD_DataRead()执行后RCS=1片选关闭,则此句前要加LCD_CmdWrite(0x00);
}
void LCD_Text(void)
{
unsigned char temp;
temp = Readreg(0x00);
temp |= 0x08;
WriteCommand(0x00,temp);
}
void LCD_on(void)
{
unsigned char temp;
temp = Readreg(0x00);
temp |= 0x04;
WriteCommand(0x00,temp);
}
//== RA8806.h ========================================================
#ifndef _RA8806_H
#define _RA8806_H
#include "STC32G.h"
#include "def.h"
#include "config.h"
/****************************** 用户定义宏 ***********************************/
sbit BRS = P4^5;//定义引脚
sbit BWR = P4^2;//9.5版本之前实验箱需要将P42与P44对调才能正常使用
sbit BRD = P4^4;
sbit BCS = P4^3; //CS1
//sbitPSB = P3^5; //PSB脚为12864的串、并通讯功能切换,我们使用8位并行接口,PSB=1320240:CS2
sbit bRST = P3^4; //17---RESETL-->Enable
sbit P6pullup = P4^0; //实验箱中给P6端口通过LED4,LED12-LED17加上拉
#define DATA_BUS P6
//#define Busy 0x80 //用于检测LCD状态字中的Busy标识
/*****************************************************************************/
//定义RA8806寄存器
#define WLCR 0x00
#define MISC 0x01
#define ADSR 0x03
#define INTR 0x0F
#define WCCR 0x10
#define CHWI 0x11
#define MAMR 0x12
#define AWRR 0x20
#define DWWR 0x21
#define AWBR 0x30
#define DWHR 0x31
#define AWLR 0x40
#define AWTR 0x50
#define CURX 0x60
#define BGSG 0x61
#define EDSG 0x62
#define CURY 0x70
#define BGCM 0x71
#define EDCM 0x72
#define BTMR 0x80
#define ITCR 0x90
#define KSCR1 0xA0
#define KSCR2 0xA1
#define KSDR0 0xA2
#define KSDR1 0xA3
#define KSDR2 0xA4
#define MWCR 0xB0
#define MRCR 0xB1
#define TPCR1 0xC0
#define TPXR 0xC1
#define TPYR 0xC2
#define TPZR 0xC3
#define TPCR2 0xC4
#define PCR 0xD0
#define PDCR 0xD1
#define PNTR 0xE0
#define FNCR 0xF0
#define FVHT 0xF1
/**********************************************************/
#define cSetb0 0x01
#define cSetb1 0x02
#define cSetb2 0x04
#define cSetb3 0x08
#define cSetb4 0x10
#define cSetb5 0x20
#define cSetb6 0x40
#define cSetb7 0x80
#define cClrb0 0xfe
#define cClrb1 0xfd
#define cClrb2 0xfb
#define cClrb3 0xf7
#define cClrb4 0xef
#define cClrb5 0xdf
#define cClrb6 0xbf
#define cClrb7 0x7f
void Init_Device(void);
void LCD_CmdWrite(unsigned char CommandByte);
void LCD_DataWrite(unsigned char DataByte);
unsigned char LCD_CmdRead(void);
unsigned char LCD_DataRead(void);
unsigned char LCD_DDRamRead(void);
void WriteCommand(unsigned char CommandReg,unsigned char CommandByte);
unsigned char Readreg(unsigned char CommandReg);
unsigned char Read_status(void);
void CheckBusy(void);
void LCD_CheckScanBusy(void);
void LCD_Graphic(void);
void LCD_Text(void);
void LCD_on(void);
void LCD_Clear(void); //unsigned char y
void LCD_Rotate90(void);
void LCD_Rotate90_Disable(void);
void Reverse_Data(void);
void Display_Window_Size(unsigned char DW_Width, unsigned char DW_Height);
void LocateXY(unsigned char x,unsigned char y);
void LCD_GotoXY(unsigned char x, unsigned char y);
void LcdInit(void);
void Test_Display(void);
void PutBMP(unsigned char *puts);
void w_dot(unsigned char x1,unsigned char x2);
void LCD_DataWritetocmd(unsigned char CmdReg,unsigned char udata);///写数据到到寄存器
//============================Reg
void SleepWakeup(void);
void LCD_SleepMode(void);
void LCD_Graphic(void);
void LCD_Text(void);
void LCD_ON(void);
void LCD_OFF(void);
void LCD_NoBlink(void);
void LCD_Blink(void);
//=============================Reg
void No_Snow_Mode(void);
void Snow_Mode(void);
//=============================Reg
void Scroll_Disable(void);
//=============================Reg
void Clr_KeyScan_INT_Flag(void);
unsigned char Get_Key(void);
unsigned char Touch_Status(void);
void clear_TP_interrupt(void);
//=============================Reg
void LCD_AlignOn(void);
void LCD_AlignOff(void);
void LCD_Bold_Font(void);
void LCD_No_Bold_Font(void);
//=============================Reg
void Gray_Mode(void);
void Only_Show_Page2(void);
void Only_Show_Page1(void);
void Show_Two_Layer(void);
void Two_Layer_OR(void);
void Two_Layer_XOR(void);
void Two_Layer_NOR(void);
void Two_Layer_AND(void);
void Access_CGRAM(void);
void Access_Page2(void);
void Access_Page1(void);
void Access_2Page(void);
//====================================================Reg
void Set_Active_Window_Size(unsigned char, unsigned char, unsigned char, unsigned char);
//====================================================Reg
void Set_Display_Window_Size(unsigned char, unsigned char);
//==================================================Reg
void LCD_GotoXY(unsigned char, unsigned char);
//===========================================================Reg
void Set_Scroll_Window_Size(unsigned char seg_start, unsigned char seg_end, unsigned char com_start, unsigned char com_end);
//===================================Reg
void Enable_KeyScan(void);
void Enable_LongKey(void);
void Enable_KeyScan_WakeUp(void);
//===================================Reg
void Enable_Touch(void);
void Enable_Touch_WakeUp(void);
//===================================Reg
unsigned char ADC_Y(void);
unsigned char ADC_X(void);
unsigned char ADC_XY(void);
//===================================Reg
void LCD_Clear(void);
//===================================Reg
void Fill_PNTR_to_DPRAM(void);
void ASCII_Block_1(void);
void ASCII_Block_2(void);
void ASCII_Block_3(void);
void ASCII_Block_4(void);
//===================================Reg
void LCD_FontSize(unsigned char);
void LCD_FontSizeNormal(void);
void LCD_FontSizeTwoTimes(void);
void LCD_FontSizeThreeTimes(void);
void LCD_FontSizeFourTimes(void);
//===================================other
void LCD_ShowStr(char *text,unsigned int t);
//=============================================================================
//general mono stn lcd driver for ra8806
//=============================================================================
void LCD_SoftwareClear(unsigned char BlackOrWhite);
void LCD_DrawPoint(unsigned int x,unsigned int y,unsigned char BlackOrWhite);
void LCD_DrawHorizontalLine(unsigned int x0,unsigned int y,unsigned int x1,unsigned char BlackOrWhite);
void LCD_DrawVerticalLine(unsigned int x,unsigned int y0,unsigned int y1,unsigned char BlackOrWhite);
void LCD_DrawLine(unsigned int x0,unsigned int y0,unsigned int x1,unsigned int y1,unsigned char BlackOrWhite);
void LCD_DrawRectangle(unsigned int x0,unsigned int y0,unsigned int x1,unsigned int y1,unsigned char BlackOrWhite);
void LCD_DrawRectangleFill(unsigned int x0,unsigned int y0,unsigned int x1,unsigned int y1,unsigned char BlackOrWhite);
void LCD_DrawCircle(unsigned int x0,unsigned int y0,unsigned char Radius,unsigned char BlackOrWhite);
void LCD_DrawCircleFill(unsigned int x0,unsigned int y0,unsigned char Radius,unsigned char BlackOrWhite);
void LCD_Draw_Picture(unsigned int x0,unsigned int y0,unsigned int width,unsigned int height,const unsigned char *picdata);
void LCD_Draw_ReversePicture(unsigned int x0,unsigned int y0,unsigned int width,unsigned int height,const unsigned char *picdata);
void LCD_PutInternalString(char *text,unsigned int t);
void LCD_PutReverseInternalString(char *text,unsigned int t);
//add by njj 2016.12.02
void LCD_CursorControl(unsigned char turn);
#endif
//== main.c =====================================================
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2026-01-18) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>
#include "config.h" //默认已包含stdio.h、intrins.h等头文件
//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
#include "delay.h"
#include "RA8806.h"
#include "NtGUI.h"
//<<AICUBE_USER_INCLUDE_END>>
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
extern void Tab0(void);
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
//<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
// 在此添加用户主函数初始化代码
//<<AICUBE_USER_MAIN_INITIAL_END>>
SYS_Init();
//Init_Device();
//<<AICUBE_USER_MAIN_CODE_BEGIN>>
// 在此添加主函数中运行一次的用户代码
BCS =1;
P6pullup = 0; //P6上拉
delay_ms(10); //10
//9.初始化GUI
NT_GUIInit();
delay_ms(3000);
//18.显示Tab界面
NT_TabCardInit();
//<<AICUBE_USER_MAIN_CODE_END>>
while (1)
{
//USBLIB_OUT_Done(); //查询方式处理USB接收的数据
_nop_();
//<<AICUBE_USER_MAIN_LOOP_BEGIN>>
// 在此添加主函数中用户主循环代码
//<<AICUBE_USER_MAIN_LOOP_END>>
}
}
////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
EnableAccessXFR(); //使能访问扩展XFR
AccessCodeFastest(); //设置最快速度访问程序代码
AccessIXramFastest(); //设置最快速度访问内部XDATA
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
//<<AICUBE_USER_PREINITIAL_CODE_BEGIN>>
// 在此添加用户预初始化代码
//<<AICUBE_USER_PREINITIAL_CODE_END>>
PORT3_Init(); //P3口初始化
PORT4_Init(); //P4口初始化
PORT6_Init(); //P6口初始化
delay_ms(1);
// USBLIB_Init(); //USB库初始化
delay_ms(1);
//<<AICUBE_USER_INITIAL_CODE_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_INITIAL_CODE_END>>
EnableGlobalInt(); //使能全局中断
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
搞定了, LCD供应商提供的例程不对, 仔细核对了RA8806说明书,修正了BRS,BWR,BRD时序,显示正常,雪花也没有了 新问题: 按STC实验箱提供的RTC例程,
void RTC_config(void)
{
INIYEAR = 24; //Y:2021
INIMONTH = 02; //M:12
INIDAY = 14; //D:31
INIHOUR = 15; //H:23
INIMIN = 43; //M:59
INISEC = 50; //S:50
INISSEC = 0; //S/128:0
ALAHOUR = 0; //闹钟小时
ALAMIN= 0; //闹钟分钟
ALASEC= 0; //闹钟秒
ALASSEC = 0; //闹钟1/128秒
//STC32G 芯片使用内部32K时钟,休眠无法唤醒
// IRC32KCR = 0x80; //启动内部32K晶振.
// while (!(IRC32KCR & 1));//等待时钟稳定
// RTCCFG = 0x03; //选择内部32K时钟源,触发RTC寄存器初始化
X32KCR = 0x80 + 0x40; //启动外部32K晶振, 低增益+0x00, 高增益+0x40.
while (!(X32KCR & 1));//等待时钟稳定
RTCCFG = 0x01; //选择外部32K时钟源,触发RTC寄存器初始化
RTCIF = 0x00; //清中断标志
RTCIEN = 0x88; //中断使能, 0x80:闹钟中断, 0x40:日中断, 0x20:小时中断, 0x10:分钟中断, 0x08:秒中断, 0x04:1/2秒中断, 0x02:1/8秒中断, 0x01:1/32秒中断
RTCCR = 0x01; //RTC使能
while(RTCCFG & 0x01); //等待初始化完成,需要在 "RTC使能" 之后判断.
//设置RTC时间需要32768Hz的1个周期时间,大约30.5us. 由于同步, 所以实际等待时间是0~30.5us.
//如果不等待设置完成就睡眠, 则RTC会由于设置没完成, 停止计数, 唤醒后才继续完成设置并继续计数.
}
执行完后,后续程序里的 延时函数
void delay_us(uint16_t us)
{
do
{
NOP(18); //(MAIN_Fosc + 500000) / 1000000 - 6
} while (--us);
}
就无法运行,执行就死机 可能是内存堆栈分配问题, LCD显示有一幅静态320240图片,9600字节 试过在实验箱例程中加delay_us(u16 us)完全没问题, 在出问题的程序前半部分用delay_us(u16 us)也没问题 这么老的方案还在用?这个芯片查了一下,不便宜啊,简单的应用就用STC32G144k246直接驱动,复杂一点的用LT7850,比用8806便宜多了。 深山老妖 发表于 2026-3-6 14:38
这么老的方案还在用?这个芯片查了一下,不便宜啊,简单的应用就用STC32G144k246直接驱动,复杂一点的用LT7 ...
原产品指定用的。 STM32F407驱动,要求换用国产芯片。
页:
[1]