I2C驱动OLED屏幕出现显示错位/乱码的解决方法
最近在做STC32G+I2C OLED屏幕+UART激光测距模块的实验,由于将屏幕刷新写在串口的中断void Uart1_Isr() interrupt 4
里面会严重影响单片机性能(可能导致卡死),于是将其改成了不断刷新距离变量LaserRanging_Char
,然后通过定时器0
定期中断将缓存发送给屏幕(OLED_BuffShow()
)
void Timer0_Isr(void) interrupt 3
{
unsigned char Freq_Hz = 1; // 20Hz刷新频率
Timer0_Counter++;
if (Timer0_Counter >= (1000/Freq_Hz)) // 1000ms/Freq_Hz
{
OLED_BuffShow();
}
}
void Timer0_Init(void) //1毫秒@33.1776MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x66; //设置定时初始值
TH0 = 0x7E; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
于是出现了这样的一幕:
WTF?这屏幕之前用着不是好好的,我寻思代码也没问题啊……
于是,我尝试了包括但不限于以下这些办法:
【失败】更换屏幕硬件
【失败】更换连接排线
【失败】更换供电电源(因为怀疑可能是供电不足导致信号出现问题)
【失败】只让
Timer0_Isr
定期刷新标志位OLED_Refesh_Flag
,然后用主程序刷新屏幕
void Timer0_Isr(void) interrupt 3
{
unsigned char Freq_Hz = 1; // 20Hz刷新频率
Timer0_Counter++;
if (Timer0_Counter >= (1000/Freq_Hz)) // 1000ms/Freq_Hz
{
OLED_Refesh_Flag = 1;
Timer0_Counter = 0;
}
}
void main(void)
{
EA = 1; //开总中断
Sys_Init(); //系统初始化
Uart1_Init(); //串口1初始化
Uart_Port_Init(); //串口端口初始化
Timer0_Init(); //定时器0初始化
OLED_Init(); //OLED初始化
OLED_LaserRanging_UI_Init(); //初始化激光测距UI
while (1)
{
key1_check(); //检查按键1
key2_check(); //检查按键2
key3_check(); //检查按键3
key4_check(); //检查按键4
if(OLED_Refesh_Flag) //刷新OLED
{
OLED_Refesh_Flag = 0;
OLED_BuffShow();
}
}
}
然而问题还是没有解决。
最终在某个论坛看到了一篇帖子,也是说OLED显示错位或乱码,其中提到可能是因为I2C通信过程中,被其他中断干扰的原因:
遂修改代码,重新下载:
void main(void)
{
EA = 1; //开总中断
// 其他代码...
while (1)
{
// 其他代码...
if(OLED_Refesh_Flag) //刷新OLED
{
OLED_Refesh_Flag = 0;
EA = 0; //关总中断
OLED_BuffShow();
EA = 1; //开总中断
}
}
}
果不其然,在给屏幕发送缓存的时候,暂时关闭总中断,就不会有乱码或者错位的情况了。
另外也尝试了一下,直接全部一堆写在中断里面也是不行的……
还是老老实实用main函数处理吧……
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-SA 4.0 协议,您可以在不商用的情况下,免费转载或修改本文内容,完整转载请注明来自 Patrick's Blog
评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果