【CH32X035评估板】--OLED显示
本帖最后由 dirty 于 2024-1-13 23:03 编辑<p> 本篇讲述用CH32X035开发板点亮OLED.所使用到的oled模块0.91",像素点128*32,驱动芯片SSD1306G.模块资料放在附件里.</p>
<p>一.硬件准备</p>
<p> 模块引脚VCC、GND、SDA、SCL,I2C驱动。SDA接PA11,SCL接PA10.</p>
<p>二.代码准备</p>
<p> 硬件I2C寄存器方案遇到标志位阻塞情况,此功能实现使用IO模拟I2C方案驱动模块。</p>
<p>1.关于引脚定义及初始化</p>
<pre>
<code>#define OLED_GPIO_PORT GPIOA
#define OLED_SDA_PIN GPIO_Pin_11//PA10
#define OLED_SCL_PIN GPIO_Pin_10//PA11
#define OLED_SCLK_Clr() GPIO_WriteBit(OLED_GPIO_PORT,OLED_SCL_PIN, 0) //IIC接口的时钟信号
#define OLED_SCLK_Set() GPIO_WriteBit(OLED_GPIO_PORT,OLED_SCL_PIN, 1)
#define OLED_SDIN_Clr() GPIO_WriteBit(OLED_GPIO_PORT,OLED_SDA_PIN, 0) //IIC接口的数据信号
#define OLED_SDIN_Set() GPIO_WriteBit(OLED_GPIO_PORT,OLED_SDA_PIN, 1)
#define IIC_READ_SDA GPIO_ReadInputDataBit(OLED_GPIO_PORT,OLED_SDA_PIN)
void OLED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = OLED_SDA_PIN|OLED_SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}</code></pre>
<p>2.关于I2c需要使用到的函数</p>
<p><1>I2C延时</p>
<pre>
<code>//延时
void IIC_delay(void)
{
u8 t=5; //3
while(t--);
}</code></pre>
<p><2>起始信号</p>
<pre>
<code>void I2C_Start(void)
{
OLED_SDIN_Set();
OLED_SCLK_Set();
IIC_delay();
OLED_SDIN_Clr();
IIC_delay();
OLED_SCLK_Clr();
IIC_delay();
}</code></pre>
<p><3>结束信号</p>
<pre>
<code>void I2C_Stop(void)
{
OLED_SDIN_Clr();
OLED_SCLK_Set();
IIC_delay();
OLED_SDIN_Set();
}</code></pre>
<p><4>等待信号响应</p>
<pre>
<code>void I2C_WaitAck(void) //测数据信号的电平
{
uint8_t cnt=0;
OLED_SDIN_Set();
IIC_delay();
OLED_SCLK_Set();
IIC_delay();
while(IIC_READ_SDA)
{
cnt++;
if(cnt>1)//250
{
I2C_Stop();
break;
}
}
OLED_SCLK_Clr();
IIC_delay();
}</code></pre>
<p><5>写入一个字节</p>
<pre>
<code>void Send_Byte(u8 dat)
{
u8 i;
for(i=0;i<8;i++)
{
OLED_SCLK_Clr();//将时钟信号设置为低电平
if(dat&0x80)//将dat的8位从最高位依次写入
{
OLED_SDIN_Set();
}
else
{
OLED_SDIN_Clr();
}
IIC_delay();
OLED_SCLK_Set();
IIC_delay();
OLED_SCLK_Clr();
dat<<=1;
}
}</code></pre>
<p>3.驱动模块使用函数.</p>
<pre>
<code>//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 mode)
{
I2C_Start();
Send_Byte(0x78);
I2C_WaitAck();
if(mode)
{
Send_Byte(0x40);
}
else
{
Send_Byte(0x00);
}
I2C_WaitAck();
Send_Byte(dat);
I2C_WaitAck();
I2C_Stop();
}</code></pre>
<p>4.驱动OLED显示函数</p>
<pre>
<code>void OLED_Display(void)
{
Delay_Ms(1500);
OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
OLED_WR_Byte(0x40,OLED_CMD);//--set start line addressSet Mapping RAM Display Start Line (0x00~0x3F)
OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
OLED_WR_Byte(0xB4,OLED_CMD);// Set SEG Output Current Brightness //设置亮度0xCF
OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常
OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常
OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
OLED_WR_Byte(0x1f,OLED_CMD);//--1/64 duty
OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
OLED_WR_Byte(0x00,OLED_CMD);//-not offset
OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
OLED_WR_Byte(0x00,OLED_CMD);
OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
OLED_WR_Byte(0x02,OLED_CMD);//
OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
OLED_WR_Byte(0xAF,OLED_CMD);
OLED_Clear();
OLED_DisplayTurn(1);
OLED_ColorTurn(0);
printf("data row:%d cloum:%d \r\n",sizeof(hz_oled)/sizeof(hz_oled),sizeof(hz_oled)/sizeof(unsigned char));
memset(OLED_GRAM,0,sizeof(OLED_GRAM));
OLED_set_buff(0,0,hz_oled,0,2,2,sizeof(hz_oled)/sizeof(hz_oled),sizeof(hz_oled)/sizeof(unsigned char),1,0);
OLED_set_buff(32,0,yw_oled,0,11,2,sizeof(yw_oled)/sizeof(yw_oled),sizeof(yw_oled)/sizeof(unsigned char),1,0);
OLED_set_buff(0,16,yw_oled,11,8,2,sizeof(yw_oled)/sizeof(yw_oled),sizeof(yw_oled)/sizeof(unsigned char),1,0);
OLED_set_buff(72,16,hz_oled,2,3,2,sizeof(hz_oled)/sizeof(hz_oled),sizeof(hz_oled)/sizeof(unsigned char),1,0);
OLED_Refresh_t();
OLED_WR_Byte(0x2E,OLED_CMD); //停止水平滚动
Delay_Ms(8000);
OLED_WR_Byte(0x2A,OLED_CMD); //左右水平滚
OLED_WR_Byte(0x00,OLED_CMD); //dummy
OLED_WR_Byte(0x00,OLED_CMD); //滚动起始页
OLED_WR_Byte(0x00,OLED_CMD); //滚动帧速
OLED_WR_Byte(0x03,OLED_CMD); //滚动结束页
OLED_WR_Byte(0x00,OLED_CMD); //水平
OLED_WR_Byte(0x2F,OLED_CMD); //启动滚动运动
}
</code></pre>
<p>5.main函数</p>
<pre>
<code>int main(void)
{
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n",SystemCoreClock);
printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
OLED_Init();
printf( "OLED_Init\r\n");
printf( "OLED to display!\r\n");
OLED_Display();
printf( "OLED display showing!\r\n");
while(1);
}
</code></pre>
<p>三.编译烧录,检查显示效果</p>
<p> 程序驱动OLED静态显示与滚动现实两种模式。静态效果见下图,动态效果见附件</p>
<div style="text-align: center;"></div>
<div style="text-align: center;">图1:oled静态显示</div>
<p> oled动态显示效果见及模块资料见文末。</p>
<p> </p>
<p> 至此,驱动oled 已达到预期效果。</p>
<p> </p>
<p>1fe978dcf979d4487a6cb5439677ab6a<br />
</p>
<p> </p>
<p>这个OLED挺小的,楼主可以试一下硬件I2C,应该效果比这个还要好。</p>
lugl4313820 发表于 2024-1-13 23:03
这个OLED挺小的,楼主可以试一下硬件I2C,应该效果比这个还要好。
<p>哇,你这秒评呀。手头只有这么个oled<img height="28" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/rolling-on-the-floor-laughing_1f923.png" width="28" /> 。两者效果差不多一样的。后面看情况再尝试下另一实现方案。</p>
dirty 发表于 2024-1-13 23:09
哇,你这秒评呀。手头只有这么个oled 。两者效果差不多一样的。后面看情况再尝试下另一实现方案。
<p>如果经常玩的话,可以搞个iic ,一个spi的,这样更加有得玩。</p>
<p>谢谢分享,期待后续!</p>
可以上传一下完整工程吗求求!
页:
[1]