OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 15754|回复: 20

原子哥,求助,用模拟I2C驱动OLED不成功

[复制链接]

15

主题

72

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
348
金钱
348
注册时间
2015-5-2
在线时间
29 小时
发表于 2015-6-27 00:27:02 | 显示全部楼层 |阅读模式
5金钱


这是逻辑分析仪读出的图形,我也没看明白,不知道是哪里出纰漏,导致模拟I2C驱动不亮OLED屏幕。感觉模拟I2C的时序延时好难把握啊!求原子哥和大神指教,源程序在附件中。调了好就没调出所以然啊
#include "myi2c.h"
#include "delay.h"
//////////////////////////////////////////////////////////////////////////////////  
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//Mini STM32开发板
//IIC 驱动函数   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2010/6/10 
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 正点原子 2009-2019
//All rights reserved
//////////////////////////////////////////////////////////////////////////////////  

//初始化IIC
void IIC_Init(void)
{     
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
 
IIC_SCL=1;
IIC_SDA=1;

}
//产生IIC起始信号
void IIC_Start(void)
{
SDA_OUT();     //sda线输出
IIC_SDA=1;    
IIC_SCL=1;
delay_us(4);
  IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
delay_us(4);
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}  
//产生IIC停止信号
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
  delay_us(4);
IIC_SCL=1; 
IIC_SDA=1;//发送I2C总线结束信号
delay_us(4);  
}

//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
SDA_OUT();    
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1;  
delay_us(2);   //对TEA5767这三个延时都是必须的
IIC_SCL=1;
delay_us(2); 
IIC_SCL=0;
delay_us(2);
    }  
}     

OLED.C
#include "oled.h"
#include "oledfont.h"    
#include "delay.h"
#include "myi2c.h"


/*********************OLED写数据************************************/
void OLED_WrDat(u8 IIC_Data)
{
IIC_Start();
IIC_Send_Byte(OLED_ADDRESS);
IIC_Send_Byte(IIC_Data);
IIC_Stop();
}


/*********************OLED写命令************************************/
void OLED_WrCmd(u8 IIC_Command)
{
IIC_Start();
IIC_Send_Byte(OLED_ADDRESS);
IIC_Send_Byte(IIC_Command);
IIC_Stop();
}


/*********************OLED 设置坐标************************************/
void OLED_Set_Pos(u8 x, u8 y)
{
OLED_WrCmd(0xb0+y);
OLED_WrCmd(((x&0xf0)>>4)|0x10);
OLED_WrCmd((x&0x0f)|0x01);
}


/*********************OLED全屏************************************/
void OLED_Fill(u8 bmp_dat)
{
u8 y,x;
for(y=0;y<8;y++)
{
OLED_WrCmd(0xb0+y);
OLED_WrCmd(0x01);
OLED_WrCmd(0x10);
for(x=0;x<X_WIDTH;x++)
OLED_WrDat(bmp_dat);
}
}

/*********************OLED复位************************************/
void OLED_CLS(void)
{
u8 y,x;
for(y=0;y<8;y++)
{
OLED_WrCmd(0xb0+y);
OLED_WrCmd(0x01);
OLED_WrCmd(0x10);
for(x=0;x<X_WIDTH;x++)
OLED_WrDat(0);
}
}

/*********************OLED初始化************************************/
void OLED_Init(void)
{
delay_init();
delay_ms(200); //这里的延时很重要

OLED_WrCmd(0xae);//--turn off oled panel
OLED_WrCmd(0x00);//---set low column address
OLED_WrCmd(0x10);//---set high column address
OLED_WrCmd(0x40);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_WrCmd(0x81);//--set contrast control register
OLED_WrCmd(Brightness); // Set SEG Output Current Brightness
OLED_WrCmd(0xa1);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
OLED_WrCmd(0xc8);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
OLED_WrCmd(0xa6);//--set normal display
OLED_WrCmd(0xa8);//--set multiplex ratio(1 to 64)
OLED_WrCmd(0x3f);//--1/64 duty
OLED_WrCmd(0xd3);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
OLED_WrCmd(0x00);//-not offset
OLED_WrCmd(0xd5);//--set display clock divide ratio/oscillator frequency
OLED_WrCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
OLED_WrCmd(0xd9);//--set pre-charge period
OLED_WrCmd(0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_WrCmd(0xda);//--set com pins hardware configuration
OLED_WrCmd(0x12);
OLED_WrCmd(0xdb);//--set vcomh
OLED_WrCmd(0x40);//Set VCOM Deselect Level
OLED_WrCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
OLED_WrCmd(0x02);//
OLED_WrCmd(0x8d);//--set Charge Pump enable/disable
OLED_WrCmd(0x14);//--set(0x10) disable
OLED_WrCmd(0xa4);// Disable Entire Display On (0xa4/0xa5)
OLED_WrCmd(0xa6);// Disable Inverse Display On (0xa6/a7)
OLED_WrCmd(0xaf);//--turn on oled panel
OLED_Fill(0x00); //初始清屏
OLED_Set_Pos(0,0);
}


STM32C8T6_Demo.7z

721.71 KB, 下载次数: 867

最佳答案

查看完整内容[请看2#楼]

刚一坛友分享的 http://www.openedv.com/posts/list/54613.htm?fromAll=0
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

2170

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
5782
金钱
5782
注册时间
2013-11-22
在线时间
1212 小时
发表于 2015-6-27 00:27:03 | 显示全部楼层
回复

使用道具 举报

15

主题

72

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
348
金钱
348
注册时间
2015-5-2
在线时间
29 小时
 楼主| 发表于 2015-6-27 00:27:03 | 显示全部楼层
回复【9楼】ndzhzsdw:
---------------------------------
模拟I2C驱动OLED也调试出来了,看芯片手册知道了每次发送一次数据后要等待一次ACK到来,即把函数IIC_Send_Byte修改一下: 
void IIC_Send_Byte(u8 txd) 
{                         
    u8 t;    
SDA_OUT();       
    IIC_SCL=0;//拉低时钟开始数据传输 
    for(t=0;t<8;t++) 
    {               
        IIC_SDA=(txd&0x80)>>7; 
        txd<<=1;     
delay_us(2);   //对TEA5767这三个延时都是必须的 
IIC_SCL=1; 
delay_us(2);  
IIC_SCL=0;
delay_us(2); 
    }
IIC_Wait_Ack();

这样就可以了
回复

使用道具 举报

15

主题

72

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
348
金钱
348
注册时间
2015-5-2
在线时间
29 小时
 楼主| 发表于 2015-6-27 14:02:21 | 显示全部楼层
自己顶顶,不要沉啊。。。。
回复

使用道具 举报

15

主题

72

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
348
金钱
348
注册时间
2015-5-2
在线时间
29 小时
 楼主| 发表于 2015-6-27 17:03:27 | 显示全部楼层
求助啊!麻烦看到的大虾指点指点啊
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-6-27 17:53:12 | 显示全部楼层
帮顶。。。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

15

主题

72

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
348
金钱
348
注册时间
2015-5-2
在线时间
29 小时
 楼主| 发表于 2015-6-27 19:55:49 | 显示全部楼层
回复【4楼】正点原子:
---------------------------------
原子哥,不知道模拟I2C调这个延时怎么控制啊,感觉这个太微妙了
回复

使用道具 举报

15

主题

72

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
348
金钱
348
注册时间
2015-5-2
在线时间
29 小时
 楼主| 发表于 2015-6-27 22:07:02 | 显示全部楼层
自己顶顶,不要沉啊。。。。源程序在附件中。调了好就没调出所以然啊
回复

使用道具 举报

15

主题

72

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
348
金钱
348
注册时间
2015-5-2
在线时间
29 小时
 楼主| 发表于 2015-6-27 23:26:29 | 显示全部楼层
回复【7楼】lycreturn:
---------------------------------
太到位了,真是及时雨  我仔细看看  谢谢啊!!!
回复

使用道具 举报

15

主题

72

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
348
金钱
348
注册时间
2015-5-2
在线时间
29 小时
 楼主| 发表于 2015-6-27 23:38:35 | 显示全部楼层
回复【8楼】ndzhzsdw:
---------------------------------
还是谢谢了    可惜不是STM32的,我主要是没弄清STM32上  延时函数延时多久合适,继续等高手。。。。
回复

使用道具 举报

7

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
183
金钱
183
注册时间
2015-6-23
在线时间
29 小时
发表于 2015-9-6 17:28:06 | 显示全部楼层
这个现在可以显示了么?lz
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2015-3-20
在线时间
1 小时
发表于 2016-4-20 23:51:30 | 显示全部楼层
用的惠特的OLED I2C的接口,看了很多程序,然后还是看文档解决了,既然路过了这里,就针对楼主的代码提提意见,希望能够帮助到大家,在对OLED屏写字节的时候,根据官方的文档,应该要给9个SCLK,前八个给字节数据从高到低,最后一个SCLK为等待oled的ACK信号,在最后一个SCLK上不要主机不要给任何的SDA,可以不读取,加入读取可以用来调试。 捕获.JPG
然后再讲讲这款OLED的数据变化与保持的时序。数据SDA要保持到一个SCLK脉冲结束,Data line is stable,在脉冲期间,如果SDA发生变化,就会产生启动或者结束信号造成错误,数据是在scl拉低了之后才会去改变。
捕获.JPG
惠特的例程软件IIC,C51中,有一个错误,就是在一个字节传输完毕之后,不能在第九个scl脉冲之前去改变SDA的值,不然会导致阻塞了ACK,而导致ACK延后发生,干扰到下一个字节的数据。
更改后的写字节如下,
[mw_shl_code=applescript,true]void Write_IIC_Byte(unsigned char IIC_Byte)
{
        unsigned char i;
        for(i=0;i<8;i++)
        {
                if(IIC_Byte & 0x80)
                        SDA_1;
                else
                        SDA_0;
                SCL_1;
                DELAY_US(1);
                SCL_0;
                IIC_Byte<<=1;
        }

        SCL_1;
        DELAY_US(1);
        SCL_0;
}[/mw_shl_code]
这款OLED的驱动器为SSD1306,经常看到很多人在写IIC程序时喜欢逐行加入delay,在这款驱动器中,除了SCL高电平保持的那个延时不可除去以外,其他的delay均可去掉。包括起始信号和结束信号。我用的是dsp28335,主频是150M,去掉delay没有任何影响,而且我的项目需要一定的实时性。但由于没有更小的延时函数,所以没有去测试,高脉冲需保持多久。另外附上惠特的给的原例程,如果要往其他平台移植软件IIC,看C51的代码就行了。在附带一个惠特的新款SPI的OLED。

IIC-OLED显示屏资料(SSD1306).zip

9.73 MB, 下载次数: 9977

惠特I2C Demo

新SPI版0.96寸OLED显示屏资料(SSD1306)蓝色.rar

4.85 MB, 下载次数: 5474

惠特OLED SPI

没有绝对完美的代码。
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2015-3-20
在线时间
1 小时
发表于 2016-4-20 23:54:01 | 显示全部楼层
帖子虽然已经很久远了,但应该也会有像我一样遇到问题的人搜索到这个帖子。
没有绝对完美的代码。
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2016-5-19
在线时间
2 小时
发表于 2016-5-21 22:28:37 | 显示全部楼层
感谢楼上的回复!
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2016-11-23
在线时间
0 小时
发表于 2016-11-23 17:46:38 | 显示全部楼层
楼主解决了吗
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2016-11-23
在线时间
0 小时
发表于 2016-11-23 17:47:26 | 显示全部楼层
楼主怎么解决的,求详情
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2017-12-6
在线时间
4 小时
发表于 2018-1-16 21:45:09 | 显示全部楼层
gentalk 发表于 2016-4-20 23:51
用的惠特的OLED I2C的接口,看了很多程序,然后还是看文档解决了,既然路过了这里,就针对楼主的代码提提意 ...

没有工程文件
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
3
金钱
3
注册时间
2019-5-12
在线时间
0 小时
发表于 2019-5-12 22:08:32 | 显示全部楼层
明天测试一下,不管成不成功,谢谢楼主
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
6
金钱
6
注册时间
2019-8-7
在线时间
1 小时
发表于 2019-8-8 15:32:26 | 显示全部楼层
楼主调通了没?我也正在做模拟IIC驱动OLED屏的项目
回复

使用道具 举报

15

主题

72

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
348
金钱
348
注册时间
2015-5-2
在线时间
29 小时
 楼主| 发表于 2019-8-26 21:55:21 | 显示全部楼层
回收站888 发表于 2019-8-8 15:32
楼主调通了没?我也正在做模拟IIC驱动OLED屏的项目

我已经转向h7了 直接参考例程即可
回复

使用道具 举报

4

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
146
金钱
146
注册时间
2019-9-14
在线时间
24 小时
发表于 2020-6-24 09:21:23 | 显示全部楼层
gentalk 发表于 2016-4-20 23:51
用的惠特的OLED I2C的接口,看了很多程序,然后还是看文档解决了,既然路过了这里,就针对楼主的代码提提意 ...

请问 这个里面的是用自带的固件库写的吧 还是软件模拟io口?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-29 10:41

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表