midfieldmaestro 发表于 2019-5-8 22:00:07

oled显示问题


为什么我的oled第二行显示就把字#include "oled.h"
#include "stm32f4xx_gpio.h"
#include "oledfont.h"
#include "delay.h"
#include "myiic.h"



void OLED_GPIO_Init(void)
{
        GPIO_Init_Pins(GPIOD,GPIO_Pin_0,GPIO_Mode_OUT);
        GPIO_Init_Pins(GPIOD,GPIO_Pin_1,GPIO_Mode_OUT);
        GPIO_Init_Pins(GPIOD,GPIO_Pin_3,GPIO_Mode_OUT);
        GPIO_Init_Pins(GPIOD,GPIO_Pin_2,GPIO_Mode_OUT);
        GPIO_Init_Pins(GPIOD,GPIO_Pin_4,GPIO_Mode_OUT);
}

void XINGC_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
       
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_Init(GPIOC,&GPIO_InitStructure);       
       
}


/**
* @brief向SSD1106写入一个字节主要用于寄存器的配置
*
* @paramdat:要写入的数据/命令
* @paramcmd:数据/命令标志 0,表示命令;1,表示数据;
*   @arg
* @retval None
*/
void Write_IIC_Data(unsigned char IIC_Data)
{
   IIC_Start();
   IIC_Send_Byte(0x78);                        //D/C#=0; R/W#=0
        IIC_Wait_Ack();       
   IIC_Send_Byte(0x40);                        //write data
        IIC_Wait_Ack();       
   IIC_Send_Byte(IIC_Data);
        IIC_Wait_Ack();       
   IIC_Stop();
}
/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{
   IIC_Start();
   IIC_Send_Byte(0x78);            //Slave address,SA0=0
        if(IIC_Wait_Ack())
        {
                while(1);
        }
   IIC_Send_Byte(0x00);                        //write command
        IIC_Wait_Ack();       
   IIC_Send_Byte(IIC_Command);
        IIC_Wait_Ack();       
   IIC_Stop();
}
void OLED_WR_Byte(uint8_t dat,uint8_t cmd)
{       
       
       
        if(cmd)
          Write_IIC_Data(dat);
        else
               Write_IIC_Command(dat);
}

/**
* @brief
*
* @param
*   @arg
* @retval None
*/
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
        OLED_WR_Byte(0xb0+(y & 0x07),OLED_CMD);/* set page start address */
        OLED_WR_Byte(x & 0x0f,OLED_CMD); /* set page start address */
        OLED_WR_Byte(((x & 0xf0)>>4)|0x10,OLED_CMD); /* set higher nibble of the column address */
}             
/**
* @brief开启OLED显示   
*
* @param
*
* @retval None
*/
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
}

/**
* @brief关闭OLED显示   
*
* @param
*
* @retval None
*/   
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
       

}                                  

/**
* @brief 清屏函数,清完屏,整个屏幕是黑色的,和没点亮一样
*
* @paramNone
*
* @retval None
*/
void OLED_Clear(void)
{
        uint8_t page,x;          
        for(page=0; page<PAGE; page++)
        {
                OLED_WR_Byte (0xb0 + page,OLED_CMD);                                    //设置页地址(0~7)
                OLED_WR_Byte (0x00,OLED_CMD);                                                              //设置显示位置—列低地址
                OLED_WR_Byte (0x10,OLED_CMD);                                                              //设置显示位置—列高地址   
               
                for(x=0; x<X_WIDTH; x++){
                        OLED_WR_Byte(0,OLED_DATA);
                }
        }

}

/**
* @brief在指定位置显示一个字符,包括部分字符
*
* @paramx:0~127 y:0~63
*   @arg mode:0,反白显示;1,正常显示                        size:选择字体 16/12
* @retval None
*/
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr)
{             
        uint8_t c=0,i=0;       
        c=chr-' ';                                                                                                                                        //得到偏移后的值                       
       
        if(x > X_WIDTH - 1)
        {
                x = 0;
                y += 2;
        }
        if(SIZE == 16)
        {
                OLED_Set_Pos(x,y);       
               
                for(i=0;i<8;i++){   //8列一个数字
                        OLED_WR_Byte(F8X16,OLED_DATA);
                }
                OLED_Set_Pos(x,y+1);
                for(i=0;i<8;i++){
                        OLED_WR_Byte(F8X16,OLED_DATA);
                }
        }
        else        if(SIZE==8)
                {
                        OLED_Set_Pos(x,y);       
                        for(i=0;i<6;i++){   
                                OLED_WR_Byte(F6x8,OLED_DATA);
                        }
                }
        else
        {       
                OLED_Set_Pos(x,y+1);       
                for(i=0;i<6;i++){
                        OLED_WR_Byte(F6x8,OLED_DATA);
                }               
        }
}

/**
* @brief计算m的n次方
*
* @param底数和指数
*   
* @retval 幂的值
*/
u32 oled_pow(u8 m,u8 n)
{
        u32 result=1;       
        while(n--)
        {
                result *= m;   
        }
        return result;
}                                  
       
/**
* @brief显示2个数字
*
* @paramx,y :起点坐标          len :数字的位数size:字体大小 mode:模式        0,填充模式;1,叠加模式 num:数值(0~4294967295);
*   @arg
* @retval None
*/
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len)
{                
        uint8_t t,temp;
        uint8_t enshow=0;                               
       
        for(t=0; t<len; t++){
                temp=(num/oled_pow(10,len-t-1))%10;//把多位数的数值分出来从高到低
               
                if(enshow == 0 && t < (len-1))//排除最后一位数第一位
                {
                        if(temp == 0)
                        {
                                OLED_ShowChar( x+(SIZEGAP/2)*t, y,'0');//最高位为0则显示为空
                                continue;
                        }
                        else
                        {
                                enshow=1;
                        }                      
                }
               OLED_ShowChar( x+(SIZEGAP/2)*t, y, temp + '0');
        }
}

/**
* @brief显示一个字符串
*
* @param        x px,page,以及需要显示的字符串
*   
* @retval None
*/
void OLED_ShowString(uint8_t x,uint8_t page,uint8_t *chr)
{
        uint8_t j=0;
        for(j=0; chr != '\0'; j++)
        {
                OLED_ShowChar(x,page,chr);
                if(SIZE==8)
                {
                        x += 6;
                        if(x > 122)//一行结束,转下一行
                        {
                                x = 0;
                                page += 2;
                        }
          }
                else if(SIZE==16)
                {
                        x += 8;
                        if(x > 120)
                        {
                                x = 0;
                                page += 2;
                        }
          }
               
        }
}

/**
* @brief显示一个汉字(在oledfont.h中)   此部分没做修改
*
* @param
*   @arg
* @retval None
*/
void OLED_ShowCHinese(uint8_t x,uint8_t page,uint8_t no)
{                                
        uint8_t t,adder=0;
        OLED_Set_Pos(x,page);       
       
        for(t=0; t<16; t++)
        {
                OLED_WR_Byte(Hzk,OLED_DATA);
                adder+=1;
        }       
       
        OLED_Set_Pos(x,page + 1);       
       
        for(t=0; t<16; t++)
        {       
                OLED_WR_Byte(Hzk,OLED_DATA);
                adder += 1;
        }                                       
}

/**
* @brief显示一个浮点数,小数部分输出3位
*
* @param输出坐标,数字,大小
*   @arg
* @retval None
*/
void OLED_FloatNumber(uint8_t x,uint8_t y, double num)
{
        u32 integerPart;
        u8 integerPartNum;
        u8gap=0;
        if(num <0 ){
                num = -num;
                OLED_ShowString(x,y,(uint8_t *)"-");
        }
       
        //让显示效果好一点
        if(SIZE==8)
        {
                x += 7;
                if(x > 121)
                {
                        x = 0;
                        y += 2;
                }       
        }
       
        if(SIZE==16)
        {
                x += 10;
                if(x > 128)
                {
                        x = 0;
                        y += 2;
                }       
}
       
        //计算整数部分几个数
        for(integerPartNum = 0,integerPart = (u32)num; integerPart != 0; integerPartNum++){
                integerPart /= 10;
        }
        if(SIZE==8)
                gap=6;
        else if(SIZE==16)
                gap=8;
        if(x > 128 - (integerPartNum+4)*gap){
                x = 0;
                y += 2;
        }

        OLED_ShowNum(x,y,(int32_t)num,integerPartNum);       
        x += integerPartNum*gap;       
        OLED_ShowString(x,y,(uint8_t *)".");
        x += gap;
        OLED_ShowNum(x,y,(int32_t)((num-integerPart)*100000),5);
}

/**
* @brief初始化SSD1306                       
*
* @param
*   @arg
* @retval None
*/          
void OLED_Init(void)
{        

        delay_ms(500);                                  
        OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
        OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
        OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
       
        OLED_WR_Byte(0x40,OLED_CMD);//--set start line addressSet Mapping RAM Display Start Line (0x00~0x3F)
       
        OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
        OLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current Brightness
       
        OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping   0xa0左右反置 0xa1正常
        OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
       
        OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
       
        OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
        OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
       
        OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset        Shift Mapping RAM Counter (0x00~0x3F)
        OLED_WR_Byte(0x00,OLED_CMD);//-not offset
       
        OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
        OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
       
        OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
        OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
       
        OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
        OLED_WR_Byte(0x12,OLED_CMD);
       
        OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
        OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
        OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
        OLED_WR_Byte(0x02,OLED_CMD);//
       
        OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
        OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
       
        OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
        OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
       
        OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel

        OLED_Clear();
        OLED_Set_Pos(0,0);        

}






void GPIO_Init_Pins(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin,GPIOMode_TypeDef GPIO_Mode)
{
        GPIO_InitTypeDef GPIO_InitStructure;
          /* Enable GPIOx, clock */
switch((uint32_t)GPIOx)
{
                case GPIOA_BASE:
    {
                        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
                        break;
    }
                case GPIOB_BASE:
    {
                        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
                        break;
    }
                case GPIOC_BASE:
    {
                        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
                        break;
    }
                case GPIOD_BASE:
    {
                        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
                        break;
    }
                case GPIOE_BASE:
    {
                        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
                        break;
    }
                case GPIOF_BASE:
    {
                        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
                        break;
    }
                case GPIOG_BASE:
    {
                        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
                        break;
    }
                case GPIOH_BASE:
    {
                        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE);
                        break;
    }
                case GPIOI_BASE:
    {
                        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOI, ENABLE);
                        break;
    }       
                default: break;
}
       
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode;

        GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
               
        GPIO_Init(GPIOx,&GPIO_InitStructure);       
        GPIO_SetBits(GPIOx,GPIO_Pin);
}



分开了

milton6799 发表于 2019-5-9 10:27:02

每一次發生都一樣位置嗎?我之前有發生過但位置每次都不同,原因是瀘波電容Layout放太遠,電源有高頻雜訊(200mhz以上)

五哥1 发表于 2019-5-9 12:19:47

本帖最后由 五哥1 于 2019-5-9 12:27 编辑

你的程序应当是OLED.C的内容,你的主程序MAIN.C的内容没有,你说显示出现问题,问题是第二行文字分开,这要看你的主程序调用了那个显示函数,显示的文字取模是否正常,用分步调试一点一点测试,看看你的问题在哪,这个是I2C的串口屏,有许多种可能造成你的问题,有时候是一个小小的书写错误。你要有耐心,一点一点地看程序,理解内容就好办了,这个弄懂了,其他的就不是事了。第一行显示正常,第一行和第二行的区别是X、Y坐标,怀疑是汉字显示程序的程序里有错误,还有你测试过,用数字显示在第二行了吗,如果用数字没有问题,哪就是汉字显示程序的问题。

huangzongwu 发表于 2019-5-9 15:07:45

milton6799 发表于 2019-5-9 10:27
每一次發生都一樣位置嗎?我之前有發生過但位置每次都不同,原因是瀘波電容Layout放太遠,電源有高頻雜訊(200m ...

对的,我现在手头上有一个类似的项目,也是显示时不时会异常,程序怎么改都没有,所以怀疑是信号干扰

milton6799 发表于 2019-5-10 11:52:39

huangzongwu 发表于 2019-5-9 15:07
对的,我现在手头上有一个类似的项目,也是显示时不时会异常,程序怎么改都没有,所以怀疑是信号干扰 ...

確認一下電源的狀況,要用更高Mhz的示波器才能量的出來
页: [1]
查看完整版本: oled显示问题