|
手上有个 SSD1306 的OLED屏,今天礼拜本来想玩一下,程序写好了调试了半天才发现屏裂了,现在没有屏了,不知道那个有屏的朋友可以测试一下代码是否正常,谢谢。
芯片:ATMEGA8
通信方式:I2C
SCLK -------- > PC0
DATA ------- > PC1
下面是代码:
#include "ATMEGA88PA.h"
#include <macros.h>
#define u8 unsigned char
#define I2C_SCLK PC0
#define I2C_DATA PC1
#define I2C_DATA_0 PORTC &= ~BIT(I2C_DATA)
#define I2C_DATA_1 PORTC |= BIT(I2C_DATA)
#define I2C_SCLK_0 PORTC &= ~BIT(I2C_SCLK)
#define I2C_SCLK_1 PORTC |= BIT(I2C_SCLK)
#define I2C_DATA_IN DDRC &= ~BIT(I2C_DATA)
#define I2C_DATA_OUT DDRC |= BIT(I2C_DATA)
#define I2C_Command 0x00
#define I2C_WData 0x40
/*-----------------------------------------
------------------------------------------*/
void PortInit(void)
{
DDRC |= 0xff;
PORTC |= 0xff;
}
/*--------------------------
----------------------------*/
void uDelay(u8 l)
{
while(l--);
}
/*
;------------------开始-----------------------------
; 开始
;SDA -----\______
;SCL --------\_____
;---------------------------------------------------
*/
void I2C_Start(void)
{
I2C_DATA_1;
I2C_SCLK_1;
uDelay(2);
I2C_DATA_0;
uDelay(2);
I2C_SCLK_0;
uDelay(2);
}
/*
;-------------------------------------------------------------
; 数据传送
;规则:SCL 为低的情况下,SDA 才能跳变
;首先传送的是数据的最高位
;搂据位 7 6 5 4 3 2 1 0 ACK(0)
;SDA _______[===][===][===][===][===][===][===][===]________
;SCL ________/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\______
;-------------------------------------------------------------
*/
void SendDATA(u8 Data)
{
u8 i;
I2C_SCLK_0;
for (i=8; i>0; i--)
{
uDelay(1);
if(Data & 0x80) //当前数据位是否是1
{
I2C_DATA_1; //当前位是1,拉高数据端
}
else
{
I2C_DATA_0; //当前位是0,拉低数据端
}
Data = Data << 1;
uDelay(1);
I2C_SCLK_1; //SCLK = 1;
uDelay(1);
I2C_SCLK_0;
}
}
/*
;---------------------------------------------
; Send_ACK
;SDA _________________
;SCL ____/-----\______
;---------------------------------------------
*/
void Send_ACK(void)
{
I2C_DATA_0;
uDelay(2);
I2C_SCLK_1;
uDelay(2);
I2C_SCLK_0;
uDelay(2);
}
/*
;---------------------------------------------
; Read_ACK
;SDA ___[=======]_____
;SCL ____/-----\______
;ack = 0
;nack = 1
;---------------------------------------------
*/
u8 I2C_ReadACK(void)
{
u8 I2C_AckFlag;
I2C_SCLK_0; //确保时钟拉低状态
I2C_DATA_IN; //设为输入,准备读取ACK
I2C_DATA_1;
I2C_SCLK_1; //拉高时钟口
uDelay(1);
if(I2C_DATA)
{
I2C_AckFlag = 0xff;
}
else
{
I2C_AckFlag = 0;
}
uDelay(1);
I2C_SCLK_0; //拉低时钟口
uDelay(1);
I2C_DATA_0;
I2C_DATA_OUT;
I2C_DATA_0;
return I2C_AckFlag;
}
/*
;---------------------------------------------
; STOP
;在数据口为低的情况下,拉高时钟 请求结束通信
;结束条件建立时间大于4μs
;
;SDA _______/-----
;SCL ____/-----
;----------------------------------------------
*/
void I2C_Stop(void)
{
I2C_SCLK_1;
uDelay(2);
I2C_DATA_1;
uDelay(2);
}
void I2C_SendCD(u8 Control, u8 Data)
{
u8 NOack,SendCoutn;
StratWrite:
I2C_Start();
SendCoutn++;
if(SendCoutn >= 30)return;
SendDATA(0x78);
NOack = I2C_ReadACK();
if(NOack)goto StratWrite;
SendDATA(Control);
NOack = I2C_ReadACK();
if(NOack)goto StratWrite;
SendDATA(Data);
NOack = I2C_ReadACK();
if(NOack)goto StratWrite;
I2C_Stop();
}
void OledInit(void)
{
int i;;
for(i=0;i<1000;i++) //
{
uDelay(200);
}
I2C_SendCD(I2C_Command,0xAE); //关闭显示
I2C_SendCD(I2C_Command,0xD5); //设置时钟分频因子,震荡频率
I2C_SendCD(I2C_Command,0x80); //[3:0],分频因子;[7:4],震荡频率
I2C_SendCD(I2C_Command,0xA8); //设置驱动路数
I2C_SendCD(I2C_Command,0X3F); //默认0X3F(1/64)
I2C_SendCD(I2C_Command,0x40); //设置显示开始行 [5:0],行数.
I2C_SendCD(I2C_Command,0xA1); // Remap
I2C_SendCD(I2C_Command,0xC8); // Scan direction
I2C_SendCD(I2C_Command,0xDA); //设置COM硬件引脚配置
I2C_SendCD(I2C_Command,0x12); //[5:4]配置
I2C_SendCD(I2C_Command,0x81); //对比度设置
I2C_SendCD(I2C_Command,0xEF); // 1~255;默认0X66(亮度设置,越大越亮)
I2C_SendCD(I2C_Command,0xD9); //设置预充电周期
I2C_SendCD(I2C_Command,0xF1); //[3:0],PHASE 1;[7:4],PHASE 2;
I2C_SendCD(I2C_Command,0xDB); //设置VCOMH 电压倍率
I2C_SendCD(I2C_Command,0x30); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
I2C_SendCD(I2C_Command,0xB0); // set page address
I2C_SendCD(I2C_Command,0xA4); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
I2C_SendCD(I2C_Command,0xA6); //设置显示方式;bit0:1,反相显示;0,正常显示
I2C_SendCD(I2C_Command,0xD3); //设置显示偏移
I2C_SendCD(I2C_Command,0X00); //默认为0
I2C_SendCD(I2C_Command,0x00); ////set lower column addres
I2C_SendCD(I2C_Command,0x10); //set higher column address
I2C_SendCD(I2C_Command,0x20); //设置内存地址模式
I2C_SendCD(I2C_Command,0x02); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
I2C_SendCD(I2C_Command,0xA1); //段重定义设置,bit0:0,0->0;1,0->127;
I2C_SendCD(I2C_Command,0x8d); //set charge pump enable
I2C_SendCD(I2C_Command,0x14);
I2C_SendCD(I2C_Command,0xAF); //开启显示
}
void main(void)
{
u8 i,n;
PortInit();
OledInit();
I2C_Start();
I2C_SendCD(I2C_Command,0xA1); // Remap
for(i=0;i<8;i++)
{
I2C_SendCD (I2C_Command,0xb0+i); //+(line-1)*2);//设置页地址(0~7)
I2C_SendCD (I2C_Command,0x0); //设置显示位置-列低地址,偏移了2列
I2C_SendCD (I2C_Command,0x10); //设置显示位置-列高地址
for(n=0;n<128;n++)
{
I2C_SendCD(I2C_WData,0xFF); //
}
}
I2C_Stop();
}
|
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|