求助帖—如何使用擎天柱AI8051最小系统板驱动iic0.96OLED屏幕
本人已经研究2天还是不能驱动屏幕,最多只能驱动屏幕显示雪花屏,请各位大佬指教,该如何学习i2c屏幕,看过一下开源项目都不能成功复现
,希望能看下能成功驱动屏幕的源代码
软键i2c和硬件i2c都尝试过,我的代码是东拼西凑来的,就不展示我的愚见了 我是这样学习的
根据OLED屏的COG IC (Chip On Glass Integrated Circuit)找到原厂数据手册(Datasheet),翻译一遍,尤其是指令集部分,看懂这个芯片有哪些功能,如何工作的,寄存器每个bit都要弄懂
还有OLED需要的工作条件,电压,时钟,扫描顺序方向,对比度,反白,滚动等等
单片机也是,IO如何配置,硬件I2C如何使用,时钟速度,上升沿下降沿,指令数据是如何传输的,哪个字节哪个位代表什么,每个bit都要弄懂
然后用单片机通过I2C把OLED的寄存器都配置一遍,接个逻辑分析仪看I2C信号,有没有按照预期工作,都正确配置了就能正常工作了,随便显示什么
然后是如何让OLED按照你的想法点亮或熄灭某个像素,显示一个点,一条线,一个字符,行列排列方式,数据发送顺序,字模和图片的显示
到处抄代码东拼西凑是学不会的
#include <STC8G.H>
#include "define.h"
#include <intrins.h>
#define RXD P30
#define TXD P31
#define SCL P32
#define SDA P33
bit I2C_Busy;
unsigned char code BMP[]=
{
#include <0.h>
};
void Delay_10ms(void)
{
unsigned char i,j;
_nop_();
_nop_();
i=144;
j=157;
do
{
while(--j);
}
while(--i);
WDT_CONTR=CLR_WDT;
}
void Delay_x10ms(unsigned char x)
{
while(--x)
Delay_10ms();
}
void I2C_Start(void)
{
I2C_Busy=1;
I2CMSCR=0x81;
while(I2C_Busy);
}
void I2C_SendData(unsigned char dat)
{
I2CTXD=dat;
I2C_Busy=1;
I2CMSCR=0x82;
while(I2C_Busy);
}
void I2C_RecvACK(void)
{
I2C_Busy=1;
I2CMSCR=0x83;
while(I2C_Busy);
}
//unsigned char I2C_RecvData(void)
//{
// I2C_Busy=1;
// I2CMSCR=0x84;
// while(I2C_Busy);
// return I2CRXD;
//}
//void I2C_SendACK(void)
//{
// I2CMSST=0x00;
// I2C_Busy=1;
// I2CMSCR=0x85;
// while(I2C_Busy);
//}
//void I2C_SendNAK(void)
//{
// I2CMSST=0x01;
// I2C_Busy=1;
// I2CMSCR=0x85;
// while(I2C_Busy);
//}
void I2C_Stop(void)
{
I2C_Busy=1;
I2CMSCR=0x86;
while(I2C_Busy);
}
void SSD1316_Write_CMD(unsigned char cmd)
{
I2C_Start();
I2C_SendData(0x78);
I2C_RecvACK();
I2C_SendData(0x00);
I2C_RecvACK();
I2C_SendData(cmd);
I2C_RecvACK();
I2C_Stop();
}
void SSD1316_Write_DATA_A(void)
{
I2C_Start();
I2C_SendData(0x78);
I2C_RecvACK();
I2C_SendData(0x40);
I2C_RecvACK();
}
void SSD1316_Write_DATA_B(unsigned char dat)
{
I2C_SendData(dat);
I2C_RecvACK();
}
void SSD1316_Write_DATA_C(void)
{
I2C_Stop();
}
void SSD1316_Clear(void)
{
unsigned char i,n;
for(i=0;i<4;i++)
{
SSD1316_Write_CMD(0xb0+i); //设置页地址(0~3)
SSD1316_Write_CMD(0x00); //设置显示位置—列低地址
SSD1316_Write_CMD(0x10); //设置显示位置—列高地址
SSD1316_Write_DATA_A();
for(n=0;n<128;n++)
{
SSD1316_Write_DATA_B(0x00);
}
SSD1316_Write_DATA_C();
}
}
void SSD1316_Display_128x32(void)
{
unsigned int i;
SSD1316_Write_CMD(0x20); //Set Memory Addressing Mode(设置内存寻址模式)
SSD1316_Write_CMD(0x01); //0x01(垂直寻址模式)
SSD1316_Write_CMD(0x21); //Set Column Address(设置列地址)
SSD1316_Write_CMD(0); //(列开始地址)
SSD1316_Write_CMD(127); //(列结束地址)
SSD1316_Write_CMD(0x22); //Set Page Address(设置页地址)
SSD1316_Write_CMD(0x00); //0
SSD1316_Write_CMD(0x03); //3
SSD1316_Write_DATA_A();
for(i=0;i<512;i++)
{
SSD1316_Write_DATA_B(BMP);
}
SSD1316_Write_DATA_C();
SSD1316_Write_CMD(0x20); //Set Memory Addressing Mode(设置内存寻址模式)
SSD1316_Write_CMD(0x02); //0x02(页寻址模式)
}
void SSD1316_Init(void)
{
SSD1316_Write_CMD(0xAE); //Set Display OFF(设置显示关)
SSD1316_Write_CMD(0xA1); //Set Segment Remap(设置列重映射)
SSD1316_Write_CMD(0xA8); //Set Multiplex Ratio(设置行通道数)
SSD1316_Write_CMD(0x1F); //31
// SSD1316_Write_CMD(0xC8); //Set COM Output Scan Direction(设置行重映射)
SSD1316_Write_CMD(0xD3); //Set Display Offset(设置垂直偏移量)
SSD1316_Write_CMD(0x00); //0
SSD1316_Write_CMD(0xD5); //Set Display Clock Divide Ratio/Oscillator Frequency(设置显示时钟分频器、振荡器频率)
SSD1316_Write_CMD(0xF0); //0xF0
SSD1316_Write_CMD(0x8D); //Charge Pump Setting(设置电荷泵)
SSD1316_Write_CMD(0x14); //0x14
SSD1316_Write_CMD(0xAF); //Set Display ON(设置显示开)
SSD1316_Clear();
// SSD1316_Write_CMD(0x81); //Set Contrast Control(设置对比度)
// SSD1316_Write_CMD(0x7F); //127
// SSD1316_Write_CMD(0xA7); //Set Normal/Inverse Display(设置反相显示)
}
void Init(void)
{
P_SW2|=EAXFR;
P3M0=0x00;
P3M1=0x00;
P5M0=0x00;
P5M1=0x00;
P3PU=0x0c;
I2CCFG=0xC1; //921.6K@11.0592M
I2CMSCR=EMSI;
I2CMSST=0x00;
EA=1;
Delay_x10ms(10);
SSD1316_Init();
}
void main(void)
{
Init();
SSD1316_Display_128x32();
while(1)
{
SSD1316_Write_CMD(0xA6);
Delay_x10ms(50);
SSD1316_Write_CMD(0xA7);
Delay_x10ms(50);
}
}
void I2C_Isr(void) interrupt 24
{
_push_(P_SW2);
P_SW2|=EAXFR;
if(I2CMSST&MSIF)
{
I2CMSST&=~MSIF;
I2C_Busy=0;
}
_pop_(P_SW2);
}
attach://76714.mp4
#include <STC8.H>
#include <intrins.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#define A0 P30
#define CS_O P31
#define CLK P32
#define MISO P33
#define MOSI P54
#define CS_F P55
#define FOSC 11059200UL
#define Command 0
#define Data 1
#define Enable 0
#define Disable 1
unsigned char FPS;
unsigned int Temp,Frame,Video;
unsigned char xdata Buffer;
unsigned char code String=
{
/*----------------------------数字----------------------------*/
0x7E,0x81,0x81,0x81,0x7E,
0x00,0x82,0xFF,0x80,0x00,
0xC2,0xA1,0x91,0x89,0x86,
0x42,0x81,0x89,0x89,0x76,
0x18,0x14,0x12,0xFF,0x10,
0x4F,0x89,0x89,0x89,0x71,
0x7C,0x8A,0x89,0x89,0x70,
0x01,0xC1,0x31,0x0D,0x03,
0x76,0x89,0x89,0x89,0x76,
0x0E,0x91,0x91,0x51,0x3E,
};
/*----------------------------延时10us@STC-Y6@11.0592MHz----------------------------*/
//void Delay_10us(void)
//{
// unsigned char i;
// i=35;
// while(--i);
//}
/*----------------------------延时x10us----------------------------*/
//void Delay_x10us(unsigned char x)
//{
// while(x--)
// Delay_10us();
//}
/*----------------------------延时10ms@STC-Y6@11.0592MHz----------------------------*/
void Delay_10ms(void)
{
unsigned char i,j;
_nop_();
_nop_();
i=144;
j=157;
do
{
while(--j);
}while(--i);
}
/*----------------------------延时x10ms----------------------------*/
//void Delay_x10ms(unsigned char x)
//{
// while(x--)
// Delay_10ms();
//}
void SPI_Write(unsigned char temp)
{
unsigned char i;
for(i=0;i<8;i++)
{
CLK=0;
temp<<=1;
MOSI=CY;
CLK=1;
}
}
unsigned char SPI_Read(void)
{
unsigned char i,temp;
for(i=0;i<8;i++)
{
temp<<=1;
CLK=0;
CLK=1;
if(MISO)
temp|=0x01;
}
return temp;
}
void SH1106_Init(void)
{
A0=Command;
SPI_Write(0xae); //关闭显示
SPI_Write(0xa8); //设置驱动路数为32路
SPI_Write(0x1f); //设置驱动路数为32路
SPI_Write(0xc8); //设置Common输出扫描方向
SPI_Write(0xa1); //设置镜像
// SPI_Write(0xa7); //设置反白
SPI_Write(0xaf); //打开显示
}
void SH1106_Set_Posi(unsigned char page,unsigned char column)
{
A0=Command;
SPI_Write(0xb0+(page&0x0f));
SPI_Write(0x00+(column&0x0f));
SPI_Write(0x12+((column&0xf0)>>4));
}
void SH1106_Clear_Screen(void)
{
unsigned char i,j;
for(i=0;i<4;i++)
{
A0=Command;
SPI_Write(0xb0+i);
SPI_Write(0x00);
SPI_Write(0x12);
A0=Data;
for(j=0;j<64;j++)
{
SPI_Write(0x00);
}
}
}
void Display_String(unsigned char page,unsigned char column,unsigned char temp)
{
unsigned char i;
SH1106_Set_Posi(page,column);
A0=Data;
for(i=0;i<5;i++)
{
SPI_Write(String);
}
}
void Display_Buffer(void)
{
unsigned char i,j;
CS_O=Enable;
for(i=0;i<4;i++)
{
SH1106_Set_Posi(i,0);
A0=Data;
for(j=0;j<64;j++)
{
SPI_Write(Buffer);
}
}
CS_O=Disable;
}
void Flash_Read(unsigned int temp)
{
unsigned char i,j;
CS_F=Enable;
SPI_Write(0x03);
SPI_Write(temp/256);
SPI_Write(temp%256);
SPI_Write(0x00);
for(i=0;i<4;i++)
{
CS_F=Enable;
for(j=0;j<64;j++)
{
Buffer=SPI_Read();
}
}
CS_F=Disable;
}
void Config_Read(void)
{
CS_F=Enable;
SPI_Write(0x03);
SPI_Write(0);
SPI_Write(0);
SPI_Write(0x00);
FPS=SPI_Read();
Video=SPI_Read();
Video<<=8;
Video|=SPI_Read();
CS_F=Disable;
}
void Init_OLED(void)
{
CS_O=Enable;
SH1106_Init();
SH1106_Set_Posi(0,0);
SH1106_Clear_Screen();
CS_O=Disable;
}
void Init(void)
{
P3M0=0x04;
P3M1=0x08;
P5M0=0x30;
P5M1=0x00;
P3PU=0x03;
P5PU=0x00;
Config_Read();
Temp=0x10000-FOSC/12/FPS;
TH0=Temp>>8; //设置定时初始值
TL0=Temp; //设置定时初始值
TF0=0; //清除TF0标志
ET0=1; //打开定时器0中断
EA=1; //打开总中断
}
void main(void)
{
Init();
if(P30)
{
Init_OLED();
TR0=1; //打开定时器0
while(1);
}
else
{
while(!P30);
Delay_10ms();
Init_OLED();
Delay_10ms();
CS_O=Enable;
Display_String(0,0,FPS/100);
Display_String(0,6,FPS%100/10);
Display_String(0,12,FPS%10);
Display_String(1,0,Video/10000);
Display_String(1,6,Video%10000/1000);
Display_String(1,12,Video%1000/100);
Display_String(1,18,Video%100/10);
Display_String(1,24,Video%10);
CS_O=Disable;
P3M0=0x00;
P3M1=0x0C;
P5M0=0x00;
P5M1=0x30;
P3PU=0x03;
P5PU=0x00;
while(1);
}
}
void Timer0(void) interrupt 1
{
unsigned char i;
Flash_Read(Frame);
if(Frame==0)
{
for(i=0;i<3;i++)
{
Buffer=0x00;
}
}
Display_Buffer();
Frame++;
if(Frame==Video)
Frame=0;
}
你的应该是SSD1306的,自己研究吧,显示雪花屏已经成功一半了 DebugLab 发表于 2024-12-25 23:52
我是这样学习的
根据OLED屏的COG IC (Chip On Glass Integrated Circuit)找到原厂数据手册(Datasheet), ...
好的谢谢佬 wnagming 发表于 2024-12-26 07:11
贡献我自己翻译的1306文件
谢谢佬 何志扬 发表于 2024-12-25 21:06
软键i2c和硬件i2c都尝试过,我的代码是东拼西凑来的,就不展示我的愚见了
能显示雪花点,说明驱动部分没有问题,正常驱动屏幕了。问题必然就是出在显示函数的使用上。正确顺序是在初始化屏幕之后,先调用清屏函数,熄灭屏幕上所有的点,然后再用显示字符或者图片的函数。
大明狐 发表于 2024-12-26 09:19
能显示雪花点,说明驱动部分没有问题,正常驱动屏幕了。问题必然就是出在显示函数的使用上。正确顺序是在 ...
他的是SSD1306的iic屏。我也有一块,最左边是VCC的
页:
[1]
2