OpenEdv-开源电子网

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

帮我解决一下,求求了。oled显示不了。

[复制链接]

3

主题

5

帖子

0

精华

新手入门

积分
8
金钱
8
注册时间
2021-11-15
在线时间
10 小时
发表于 2021-11-21 20:35:38 | 显示全部楼层 |阅读模式
12金钱
i2c.c
void IIC_Init(void)
{                                             
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOB, ENABLE );        //使能GPIOB时钟
         
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);         //PB6,PB7 输出高
}
//产生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);                                                                  
}

u8 IIC_Wait_Ack(void)
{
        u8 ucErrTime=0;
        SDA_IN();      //SDA设置为输入  
        IIC_SDA=1;delay_us(1);         
        IIC_SCL=1;delay_us(1);         
        while(READ_SDA)
        {
                ucErrTime++;
                if(ucErrTime>250)
                {
                        IIC_Stop();
                        return 1;
                }
        }
        IIC_SCL=0;//时钟输出0           
        return 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);   
                IIC_SCL=1;
                delay_us(2);
                IIC_SCL=0;      
                delay_us(2);
    }         
}

oled.c
void OLED_Refresh_Gram(void)
{
        u8 i,n;                    
        for(i=0;i<8;i++)  
        {  
                OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
                OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
                OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
                for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n],OLED_DATA);
        }   
}
void OLED_WR_Byte(u8 dat,u8 cmd)
{
        IIC_Start();
  IIC_Send_Byte(0x78)        ;
  IIC_Wait_Ack();
        if(cmd)
         IIC_Send_Byte(0x40);
        else
                IIC_Send_Byte(0x00);
        IIC_Wait_Ack();
        IIC_Send_Byte(dat);
        IIC_Wait_Ack();
        IIC_Stop();
  
}                        


//开启OLED显示   
void OLED_Display_On(void)
{
        OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
        OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
        OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}
//关闭OLED显示     
void OLED_Display_Off(void)
{
        OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
        OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
        OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}                                            
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!         
void OLED_Clear(void)  
{  
        u8 i,n;  
        for(i=0;i<8;i++)for(n=0;n<128;n++)OLED_GRAM[n]=0X00;  
        OLED_Refresh_Gram();//更新显示
}
//画点
//x:0~127
//y:0~63
//t:1 填充 0,清空                                 
void OLED_DrawPoint(u8 x,u8 y,u8 t)
{
        u8 pos,bx,temp=0;
        if(x>127||y>63)return;//超出范围了.
        pos=7-y/8;
        bx=y%8;
        temp=1<<(7-bx);
        if(t)OLED_GRAM[x][pos]|=temp;
        else OLED_GRAM[x][pos]&=~temp;            
}

//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示                                 
//size:选择字体 12/16/24
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)
{                                 
        u8 temp,t,t1;
        u8 y0=y;
        u8 csize=(size/8+((size%8)?1:0))*(size/2);                //得到字体一个字符对应点阵集所占的字节数
        chr=chr-' ';//得到偏移后的值                 
    for(t=0;t<csize;t++)
    {   
                if(size==12)temp=asc2_1206[chr][t];                  //调用1206字体
                                                                       
        for(t1=0;t1<8;t1++)
                {
                        if(temp&0x80)OLED_DrawPoint(x,y,mode);
                        else OLED_DrawPoint(x,y,!mode);
                        temp<<=1;
                        y++;
                        if((y-y0)==size)
                        {
                                y=y0;
                                x++;
                                break;
                        }
                }           
    }         
}
//m^n函数
u32 mypow(u8 m,u8 n)
{
        u32 result=1;         
        while(n--)result*=m;   
        return result;
}                                 

//显示字符串
//x,y:起点坐标  
//size:字体大小
//*p:字符串起始地址
void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size)
{      
    while((*p<='~')&&(*p>=' '))//判断是不是非法字符!
    {      
        if(x>(128-(size/2))){x=0;y+=size;}
        if(y>(64-size)){y=x=0;OLED_Clear();}
        OLED_ShowChar(x,y,*p,size,1);         
        x+=size/2;
        p++;
    }  
      
}         
//初始化SSD1306                                            
void OLED_Init(void)
{        

                                             
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOB, ENABLE );        //使能GPIOB时钟
         
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);         //PB6,PB7 输出高
                                                            
        delay_ms(100);
                                          
        OLED_WR_Byte(0xAE,OLED_CMD); //关闭显示
        OLED_WR_Byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率
        OLED_WR_Byte(80,OLED_CMD);   //[3:0],分频因子;[7:4],震荡频率
        OLED_WR_Byte(0xA8,OLED_CMD); //设置驱动路数
        OLED_WR_Byte(0X3F,OLED_CMD); //默认0X3F(1/64)
        OLED_WR_Byte(0xD3,OLED_CMD); //设置显示偏移
        OLED_WR_Byte(0X00,OLED_CMD); //默认为0

        OLED_WR_Byte(0x40,OLED_CMD); //设置显示开始行 [5:0],行数.
                                                                                                            
        OLED_WR_Byte(0x8D,OLED_CMD); //电荷泵设置
        OLED_WR_Byte(0x14,OLED_CMD); //bit2,开启/关闭
        OLED_WR_Byte(0x20,OLED_CMD); //设置内存地址模式
        OLED_WR_Byte(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
        OLED_WR_Byte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127;
        OLED_WR_Byte(0xC0,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
        OLED_WR_Byte(0xDA,OLED_CMD); //设置COM硬件引脚配置
        OLED_WR_Byte(0x12,OLED_CMD); //[5:4]配置
                 
        OLED_WR_Byte(0x81,OLED_CMD); //对比度设置
        OLED_WR_Byte(0xEF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮)
        OLED_WR_Byte(0xD9,OLED_CMD); //设置预充电周期
        OLED_WR_Byte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2;
        OLED_WR_Byte(0xDB,OLED_CMD); //设置VCOMH 电压倍率
        OLED_WR_Byte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;

        OLED_WR_Byte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
        OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示                                                              
        OLED_WR_Byte(0xAF,OLED_CMD); //开启显示         
        OLED_Clear();
}

main.c
int main()
{
        IIC_Init();
        OLED_Init();
      
        OLED_ShowChar(100,24,'a',12,1);
        OLED_Refresh_Gram();
        while(1);

}


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

12

主题

3399

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8676
金钱
8676
注册时间
2020-5-11
在线时间
4150 小时
发表于 2021-11-22 09:57:51 | 显示全部楼层
本帖最后由 LcwSwust 于 2021-11-22 10:09 编辑

首先试一下OLED寄存器写入值与读出的值是否相等,若相等说明单片机与OLED间的通信正常,检查设置值是否正确、是否打开了显示开关等;
若不相等,说明单片机与OLED间的通信不正常,检查是否有收到OLED发出的ACK信号,换个设备地址再试一下。
有示波器吗?测下波形,看SDA、SCL是否如如你所愿置高置低、是否收到OLED发出的ACK信号,波特率是否超出OLED的承受范围、
OLED各引脚电压是否正常比如电源是压够不够。没示波器的话推荐DS100,若要继续干这一行必须要有示波器。
建议:程序别整这么多,源码(整个工程以及用到的库,让别人能直接编译的)做个压缩包传上来,核心代码贴上就行,你看你的代码里找不到SDA_IN的定义,也不知是否正确。

还有,之前似乎说是从例程改的,到底改了哪些?例程为何不能直接用?OLED卖家有没有给例程?
这个OLED有没有正常工作过?万一这片OLED坏了你还有没有可更换的?
这些天你想过啥办法?做过啥调试?
问题要描述清晰,别光贴代码,万一不是代码的问题呢。


专治疑难杂症
回复

使用道具 举报

21

主题

218

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2325
金钱
2325
注册时间
2017-12-11
在线时间
495 小时
发表于 2021-11-22 10:17:28 | 显示全部楼层
可以在论坛搜搜例程啊,对比下哪里有问题
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-14 10:47

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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