- 打卡等级:以坛为家II
- 打卡总天数:501
- 最近打卡:2025-05-09 08:51:43
荣誉版主
- 积分
- 3541
|
发表于 2024-9-11 20:24:57
|
显示全部楼层
本帖最后由 浦江一水 于 2024-9-11 20:28 编辑
学习实验"AI8051U驱动0.96寸单色OLED12864实验程序 SPI+DMA"
实验代码取自官方DEMO文件包(第77号), 只是做了两点微小的调整.
一是改变了所显示的汉字, 算是做一次小字库点阵模制作练习. (对于OLED SSD1306显示屏. 取模为: 从左到右,从上到下,纵向排列高位在下.)
二是加入了定时器0的1微秒中断, 利用他做显示速度测试, 进一步了解了SPI+DMA的传输速度.
实验结果先看视频...
视频中可见, 循环显示两幅图片,( 每幅1024字节.)
第一幅图显示用时1300us, 这是指: 将图片数据先传入显示缓存区, 再启动DMA传输, 再等待DMA传输结束的总用时.
第二幅图显示用时589us, 这是指: 不算将图片数据先传入显示缓存区的时间, 仅从启动DMA传输后, 等待DMA传输结束的这一段用时.
这一实验结果, 与官方的DEMO文献描述相比较, 应该是基本接近和吻合的.
存在一点误差, 是因为定时器中断的重载入数据, 是按照20MHz中断函数来推算的,不是非常精确的.
同时也要认识到: 显示一幅图片的用时, 与传输这副图片数据的用时, 概念有所区别.
最后,贴一下相关改动部分的主函数和定时器中断函数的代码, 供有兴趣的坛友看看...
//全局变量说明
char S[80]; //字符串显示缓存
unsigned int Delaynus; //微秒计数器
......
void main(void)
{
u16 i;
EAXFR = 1; //允许访问扩展寄存器
WTST = 0;
CKCON = 0;
P0M1 = 0; P0M0 = 0; //设置为准双向口
P1M1 = 0; P1M0 = 0; //设置为准双向口
P2M1 = 0; P2M0 = 0; //设置为准双向口
P3M1 = 0; P3M0 = 0; //设置为准双向口
P4M1 = 0; P4M0 = 0; //设置为准双向口
P5M1 = 0; P5M0 = 0; //设置为准双向口
P6M1 = 0; P6M0 = 0; //设置为准双向口
P7M1 = 0; P7M0 = 0; //设置为准双向口
LCD12864_config();
Timer0_Init();
EA = 1;
while(1)
{
for(i=0; i<1024; i++) DisTmp = 0; //清除显存
SPI_DMA_TRIG(DisTmp);
while(B_SPI_DMA_busy); //等待SPI DMA完成
printf_ascii(0, 0, "TestOLED12864 AI8051U");
for(i=0; i<7; i++) WriteHZ16((u8)(8+i*16),2,i);
printf_ascii_10x24(0,5,"-12.345 678");
LCD_delay_ms(1000);
Delaynus=0; //计数清零
for(i=0; i<1024; i++) DisTmp = gImage_picture1; //将图片装载到显存
SPI_DMA_TRIG(DisTmp); //启动DMA传输指令,用时1us
while(B_SPI_DMA_busy); //等待SPI DMA完成
sprintf(S,"%03dus",Delaynus);//显示一幅图, 用时 1300us
printf_ascii(0,0,S); //显示用时
LCD_delay_ms(1000);
for(i=0; i<1024; i++) DisTmp = gImage_picture2; //将图片装载到显存
SPI_DMA_TRIG(DisTmp); //启动DMA传输指令,用时1us
Delaynus=0; //计数清零
while(B_SPI_DMA_busy); //等待SPI DMA完成
sprintf(S,"%03dus",Delaynus); //传输一幅图数据用时 589us
printf_ascii(0,0,S); //显示
LCD_delay_ms(1000);
}
}
//========================================================================
// 函数: void timer0_Init (void)
// 描述: timer0初始化. //1微秒@40.000MHz
//========================================================================
void Timer0_Init(void)
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xD8; //设置定时初始值
TH0 = 0xFF; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //允许T0中断
}
//========================================================================
// 函数: void timer0_int (void) interrupt TIMER0_VECTOR
// 描述: timer0中断函数.
//========================================================================
void timer0_int (void) interrupt 1
{
Delaynus++; //us计数器+1
}
|
|