u014787043
昵称都难找
2015-01-07 02:42

mega8驱动OLED(ssd1306)遇问题

  • 驱动程序
  • oled
  • mega8
  • ssd1306

最近想用mega8驱动新买的ssd1306,也就是Oled屏,网上51和stm32的例程很多,可是唯独不见基于AVR的例程。于是直接参照51的例程,自己写了驱动程序。编译完,下载到mega8上测试,却连亮都没亮一下。昨天检查了很多遍程序,实在看不出什么问题,所以来此请教一下高手们,感激不尽!下面是驱动程序部分和main

ssd1306.h:


/*--------------------------------------------------------
name:  mega8驱动ssd1306 OLed
date:  2015.01.02
coder:J
续:  2015.01.06   没法亮屏

--------------------------------------------------------*/
#include<iom8v.h>
#include<macros.h>
#include "asiic.h"
#define uchar unsigned char
#define uint unsigned int
const xtal = 8;

//延时函数
void delay_ms(uchar n)
{
 uint i;
 for(i=n;i<(uint)(xtal*143-2);i++);//xtal为晶振大小,单位为MHz
}

void delay_us(uint a)
{
    uint i;
    for(i = 0;i < a;i++)
    {
        asm("nop");
    }
}
/*-------------------------------------------------------
注意:  该模块不和5.0V接口兼容,所以请大家在使用的时候一定
       要小心,别直接接到5V的系统上去,接5V 系统时,应串接
       3.3K电阻,电源依然是3.3V。

所用模块为4线SPI:每个数据长度均为8位,在SCLK的上升沿,数
                  据从SDIN移入到SSD1306,并且是高位在前的

  D0  -> PB5   串行时钟线SCLK
  D1  -> PB4   串行数据线SDIN
  RES -> PB3   硬复位OLED
  D/C  -> PB2  命令/数据标志(0,读写命令;1,读写数据)
  CS  -> OLED片选信号(低电平有效)
-------------------------------------------------------*/
//---------------宏定义---------------------------------
//SCLK
#define SCLK_high  (PORTB |= (1<<PB5))
#define SCLK_low   (PORTB &=~(1<<PB5))

// SDIN
#define DSDIN_high (PORTB |= (1<<PB4))
#define DSDIN_low  (PORTB &=~(1<<PB4))

#define RES_high   (PORTB |= (1<<PB3))
#define RES_low    (PORTB &=~(1<<PB3))

//写数据
#define DC_high    (PORTB |= (1<<PB2)) 
//写命令
#define DC_low     (PORTB &=~(1<<PB2))
//------------------------------------------------------
//端口初始化
void port_init(void)
{
  DDRC  = 0xff;
  PORTC = 0x00;
  PORTC |= 0x01;

  DDRB = 0xfe;
  PORTB = 0x00;
  PORTB |=(1<<PB1);
 /* 
  SCLK_high;
  DSDIN_high;
  DC_low;
  RES_high;
  */
}
//向Oled写入数据
void Oled_WR_Data(uchar data)
{
   uchar i;
   uchar temp = 0;
   DC_high;  //写数据
   SCLK_low;
   for(i=0;i<8;i++)
   {
      temp =data & 0x80;
     // SCLK_high;//高位在前
      if(temp==0)
      {  DSDIN_low;  }
      else
      {  DSDIN_high;   }
      SCLK_high;
      delay_us(10);
      SCLK_low;
      data <<= 1;
   }
  // DSDIN_high;
}
//向Oled写入命令
void Oled_WR_Cmd(uchar cmd)
{
  uchar i;
  uchar temp = cmd & 0x80;
  DC_low;   //写命令
  SCLK_low;
  for(i=0;i<8;i++)
  {
   // SCLK_high;  //高位在前
    if(temp==0)
    {  DSDIN_low; }
    else
    {  DSDIN_high;  }
    SCLK_high;
    delay_us(10);
    SCLK_low;
    cmd <<= 1;
  }
//  DSDIN_high;
}

//满屏
void Oled_Fill(uchar dat)
{
   uchar x,y;
   for(y=0;y<8;y++)
   {
     Oled_WR_Cmd(0xb0 + y);
     Oled_WR_Cmd(0x01);
     Oled_WR_Cmd(0x10);
     for(x=0;x<128;x++)
        Oled_WR_Data(dat);
   }
}

//清屏
void Oled_Cls(void)
{
   uchar x,y;
   for(y=0;y<8;y++)
   {
     Oled_WR_Cmd(0xb0 + y);
     Oled_WR_Cmd(0x01);
     Oled_WR_Cmd(0x10);
     for(x=0;x<128;x++)
        Oled_WR_Data(0);
   }
}

//初始光标位置
void Oled_Set_Pos(uchar x,uchar y)
{
   Oled_WR_Cmd(0xb0 + y);
   Oled_WR_Cmd(((x & 0xf0)>>4)|0x10);
   Oled_WR_Cmd((x & 0x0f)|0x01);
}
// OLED的初始化
void Oled_init(void)
{
   SCLK_high;
   RES_low;
   delay_ms(100);
   RES_high;

//从上电到下面开始初始化要有足够的时间,即等待RC复位完毕   

  Oled_WR_Cmd(0xae);//关闭显示
  Oled_WR_Cmd(0x00);//---set low column address
  Oled_WR_Cmd(0x10);//---set high column address
  Oled_WR_Cmd(0x40);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
  Oled_WR_Cmd(0x81);//--对比度设置
  Oled_WR_Cmd(0xcf); // Set SEG Output Current Brightness
  Oled_WR_Cmd(0xa1);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
  Oled_WR_Cmd(0xc8);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
  Oled_WR_Cmd(0xa6);//--set normal display
  Oled_WR_Cmd(0xa8);//设置驱动路数(1 to 64)
  Oled_WR_Cmd(0x3f);//--1/64 默认0X3F
  Oled_WR_Cmd(0xd3);//-set display offset   Shift Mapping RAM Counter (0x00~0x3F)
  Oled_WR_Cmd(0x00);//-not offset
  Oled_WR_Cmd(0xd5);//--set display clock divide ratio/oscillator frequency
  Oled_WR_Cmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
  Oled_WR_Cmd(0xd9);//设置预充电周期
  Oled_WR_Cmd(0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
  Oled_WR_Cmd(0xda);//--set com pins hardware configuration
  Oled_WR_Cmd(0x12);
  Oled_WR_Cmd(0xdb);//--set vcomh
  Oled_WR_Cmd(0x40);//Set VCOM Deselect Level
  Oled_WR_Cmd(0x20);//设置内存地址模式 (0x00/0x01/0x02)
  Oled_WR_Cmd(0x02);//
  Oled_WR_Cmd(0x8d);//电荷泵设置
  Oled_WR_Cmd(0x14);//--set(0x10) disable
  Oled_WR_Cmd(0xa4);// Disable Entire Display On (0xa4/0xa5)
  Oled_WR_Cmd(0xa6);// Disable Inverse Display On (0xa6/a7) 
  Oled_WR_Cmd(0xaf);//--开启显示
  Oled_Fill(0xff); 
  //Oled_Cls(); //初始清屏
  Oled_Set_Pos(0,0);//初始位置
}


//==============================================================
//函数名:Oled_6x8_Str(uchar x,uchar y,uchar *p)
//功能描述:写入一组标准ASCII字符串
//参数:显示的位置(x,y),y为页范围0~7,要显示的字符串
//返回:无
//==============================================================  
void Oled_6x8_Str(uchar x,uchar y,uchar ch)
{
  uchar c=0,i=0,j=0;      
  while (ch)
  {    
    ch -= 32;
    if(x > 126)
    {
       x = 0;  y++;
    }
    Oled_Set_Pos(x,y);    
    for(i=0;i<6;i++)     
      Oled_WR_Data(f6x8[ch][i]);  
    x += 6;
    j ++;
  }
}

main.c:

#include <iom8v.h>
#include <macros.h>
#include "ssd1306.h"

uchar count = 0;

void main(void)
{ 
   port_init();
   Oled_init();
   Oled_Fill(0xff);

   while(1)
   {
     if((PINB&(1<<PB0))==0)
     {
       while(!(PINB&(1<<PB0)));
       if(count>=10)
         count = 0;
       else
         count += 1;
     }
     delay_ms(5000);
     Oled_Cls();
     Oled_6x8_Str(2,2,count);
     delay_ms(5000);
     Oled_Fill(0x00);
   }
}
  • 点赞
  • 回答
  • 收藏
  • 复制链接分享

1条回答

为你推荐

换一换