之前论坛上有些朋友提过,使用论坛上的老刘示波器等等例程的时候,
屏幕会花屏或者内容错乱。
大家一直在程序方面寻找原因。
前段时间发现,可能是市面上的OLED屏幕模块质量问题,
如果IO口启用了内部上拉电阻(PxPU),有些屏幕模块可以正常显示,
而有些屏幕模块就会显示混乱,关掉上拉电阻就又能正常显示。
不知道具体原因,但并不是程序本身的问题。
大明狐 发表于 2025-6-19 11:58
看到楼上的IO口配置部分,突然想起一个问题,补充在这里就不另开帖子了。
之前论坛上有些朋友提过,使用论 ...
SPI-OLED12864, 抗干扰 强:
#SS, SCLK, MOSI, 都设置成强推挽,抗干扰肯定强 !!!
I2C-OLED12864, 抗干扰 弱:
SCL, SDA, 都设置成【准双向口/弱上拉 + 上拉电阻】,抗干扰一般,容易【高 被拉 低】
===准双向口/弱上拉 的输出 低的能力 和强推挽输出低的能力一样强,外界干扰打不过这个低
SCL, SDA, 都设置成【开漏 + 上拉电阻】,抗干扰一般,容易【高 被拉 低】
===开漏 输出 低的能力 和强推挽输出低的能力一样强,外界干扰打不过这个低
所以 I2C 的问题是 高 容易被干扰到 低,解决方案:
===1,卓教授,外加 500欧到 1K的强上拉,这样不容易被干扰到低
卓老师后来重新布线,干扰小了,I2C 加 3K ~ 10K 上拉电阻即可
===2,直接改用 SPI 接口,
#SS, SCLK, MOSI, 都设置成强推挽,抗干扰肯定强 !!!
https://www.bilibili.com/video/BV1P67nztEYj?t=2.2
https://www.bilibili.com/video/BV1XdN4ztEvp?t=107.4
https://www.bilibili.com/video/BV1tXNCzeEUx?t=5.4
https://www.bilibili.com/video/BV169K8zJE1t?t=273.4
非常实用的内容。感谢分享! 试了一下SSD1306芯片的OLED12864屏幕专有的显示方式{:huaixiao:}
把43张 76×64像素的图片取模成一个大数组 DANCER;
屏幕的寻址模式设置成 【水平地址模式】
用OLED的设置显示范围的指令 0x21和 0x22 把屏幕控制范围缩小到图片的大小
void DMA_OLED_Set_Area( u8 x, u8 y, u8 width, u8 height )
{
u8 CMD;
u8 page = ( height % 8 ) ? ( height/8+1 ) : ( height/8 );
if( x<0 || (x+width-1)>127 ) return; //坐标范围不可以超出屏幕范围
if( y<0 || (y+ page-1)>7 ) return;
CMD= 0x21; //设置列范围
CMD= x; //设置起始列
CMD= x+width-1; //设置结束列
CMD= 0x22; //设置行范围
CMD= y; //设置起始行
CMD= y+page-1; //设置结束行
DMA_SendCommand( CMD, 6 );
}
然后直接发送图片里的所有数据
DMA_OLED_Set_Area ( 26, 0, 76, 64 ); // 设置显示区域
DMA_SendData ( DANCER, 76*8*43 ); // 发送所有数据
DMA_OLED_Set_Area( 0, 0, 128, 64 ); // 恢复全屏区域
显示完一组内容之后,就可以重新设置其他显示区域
显示效果:
814
===============================================
还可以直接创建一个显示图片的函数
void DMA_OLED_ShowImage( u8 x, u8 y, u8 *pic, u8 width, u8 height )
{
u16 bytes = ( height % 8 ) ? ( (height/8+1)*width ) : ( height/8*width ); //计算图片总字节数
DMA_OLED_Set_Area( x, y, width, height ); //设置将控制区域为图片大小
DMA_SendData ( pic, bytes ); //发送图片所有数据
DMA_OLED_Set_Area( 0, 0, 128, 64 ); //恢复控制区域为全屏
}
不过这两个指令并不是通用指令
SSD1036、SSD1315、SSD1309等等支持,
SH1306等等不支持,还是要老老实实一行一行发送
定位函数
void DMA_OLED_Set_Pos( u8 x, u8 y )
{
u8 CMD;
x += 0;
CMD = ( 0xB0 + y ); // 设置起始列地址
CMD = ( x & 0x0F ); // 设置起始行地址低八位
CMD = ( 0x10 + ( x >> 4 ) ); // 设置起始行地址高八位
DMA_SendCommand( CMD, 3 );
}
两种清屏函数
void DMA_OLED_Clear() // 通用
{
u8 DAT={0};
u8 i;
for(i=0;i<8;i++)
{
DMA_OLED_Set_Pos( 0, i );
DMA_SendData( DAT, 128 );
}
}
void DMA_OLED_Clear() // 适合SSD1306等,不适合SH1106
{
u8 DAT={0};
DMA_OLED_Set_Pos( 0, 0 );
DMA_SendData( DAT, 1024 );
}
通用的显示图片函数
void DMA_OLED_ShowImage( u8 x, u8 y, u8 *pic, u8 width, u8 height )
{
u8 i;
u8 pages = ( height % 8 ) ? ( height/8+1 ) : ( height/8 );
for( i=0; i<pages; i++ )
{
DMA_OLED_Set_Pos( x, y+i );
DMA_SendData ( pic + width*i, width );
}
}
815
大明狐 发表于 2025-6-17 15:33
I2C的发送和接收数据共用一条线(SDA),SPI是分成发送(MOSI)和接收(MISO)两条线。
因为控制OLED只需 ...
您解释的准确,精炼,易懂,非常感谢,又学到新知识了。 神农鼎 发表于 2025-6-19 09:56
进行了 MOSI / MISO 切换
加油,我对 www.STCAI.com 充满期待,这两年确实发展的很快,
STCAI 是目前我认为单片机圈内生态做的最好的,
有问必答,真的是贴心。
学习了,真的好 为什么不转向vscode开发? 410445549 发表于 2025-6-28 17:35
为什么不转向vscode开发?
那只是一个 编辑器,我们论坛有这个版块,很多坛友在用
页:
1
[2]