一、IIC(软件IIC)相关代码:
此部分属于IIC协议的内容,(如果使用IO模拟IIC)只有IIC起始位,停止位,等待应答等;
直接对IO口拉高拉低。
void IIC_delay(void)
{
uint8_t t = 3;
while (t--)
;
}
void I2C_Start(void)
{
OLED_SDA_Set();
OLED_SCL_Set();
// IIC_delay();
OLED_SDA_Clr();
// IIC_delay();
OLED_SCL_Clr();
// IIC_delay();
}
void I2C_Stop(void)
{
OLED_SDA_Clr();
OLED_SCL_Set();
// IIC_delay();
OLED_SDA_Set();
}
void I2C_WaitAck(void)
{
OLED_SDA_Set();
// IIC_delay();
OLED_SCL_Set();
// IIC_delay();
OLED_SCL_Clr();
// IIC_delay();
}
二、写指令、写数据:
此部分属于设备与OLED沟通的“桥梁”,无论是数据还是指令,都需要这部分来支持。事实上,这部分也属于IIC协议的范畴。如果使用硬件IIC,则把写数据的方式改成硬件IIC的函数即可。
void Send_Byte(uint8_t dat)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
if (dat & 0x80)
{
OLED_SDA_Set();
}
else
{
OLED_SDA_Clr();
}
// IIC_delay();
OLED_SCL_Set();
// IIC_delay();
OLED_SCL_Clr();
dat <<= 1;
}
}
//mode:表示写的是命令还是数据
void OLED_WR_Byte(uint8_t dat, uint8_t mode)
{
I2C_Start();
Send_Byte(0x78);
I2C_WaitAck();
if (mode)
{
Send_Byte(0x40);
}
else
{
Send_Byte(0x00);
}
I2C_WaitAck();
Send_Byte(dat);
I2C_WaitAck();
I2C_Stop();
}
三、OLED初始化:
这部分是对IO口的初始化(如果是硬件IIC,则不需要前面4句),作用是设置显示的方向,亮度,扫描方式,等等。
void OLED_Init(void)
{
atm_gpio_setup(OLED_SCL); //时钟线
atm_gpio_set_output(OLED_SCL);//设为输出io
atm_gpio_setup(OLED_SDA); //
atm_gpio_set_output(OLED_SDA);
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 address Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_WR_Byte(0xB0, OLED_CMD);
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(0xC0, 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(0x30, 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_Clear();
OLED_WR_Byte(0xAF, OLED_CMD);
}
四、OLED屏幕操作:
顾名思义,方向翻转,颜色反转,息屏亮屏
void OLED_ColorTurn(uint8_t i)
{
if (i == 0)
{
OLED_WR_Byte(0xA6, OLED_CMD);
}
if (i == 1)
{
OLED_WR_Byte(0xA7, OLED_CMD);
}
}
void OLED_DisplayTurn(uint8_t i)
{
if (i == 0)
{
OLED_WR_Byte(0xC8, OLED_CMD);
OLED_WR_Byte(0xA1, OLED_CMD);
}
if (i == 1)
{
OLED_WR_Byte(0xC0, OLED_CMD);
OLED_WR_Byte(0xA0, OLED_CMD);
}
}
void OLED_DisPlay_On(void)
{
OLED_WR_Byte(0x8D, OLED_CMD);
OLED_WR_Byte(0x14, OLED_CMD);
OLED_WR_Byte(0xAF, OLED_CMD);
}
void OLED_DisPlay_Off(void)
{
OLED_WR_Byte(0x8D, OLED_CMD);
OLED_WR_Byte(0x10, OLED_CMD);
OLED_WR_Byte(0xAE, OLED_CMD);
}
五、字符汉字显示(常规版)
这个显示方式定位的位置x取0到128,y取0到7;显示位置较为局限。
优点:模拟IIC、硬件IIC均可使用。
缺点:不能画图,速率太慢。硬件IIC可以采用第六单元的方式;
#if point8_mode
#define OLED_width 128
#define OLED_height 64
#define page 8 //(0~7)
void OLED_Clear(void)
{
uint8_t i, n;
for (i = 0; i < 8; i++)
{
OLED_WR_Byte(0xb0 + i, OLED_CMD); //设置页地址
OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址
OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址
// OLED_WR_Byte(0x10, OLED_CMD); //列地址高4位
// OLED_WR_Byte(0x00, OLED_CMD); //列地址低4位
for (n = 0; n < 128; n++)
{
OLED_WR_Byte(0x00, OLED_DATA); //清除所有数据
}
}
}
//设置起始地址
void OLED_address(uint8_t x, uint8_t y)
{
OLED_WR_Byte(0xb0 + y, OLED_CMD); //设置页地址
OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD); //列地址高4位
OLED_WR_Byte((x & 0x0f), OLED_CMD); //列地址低4位
}
void OLED_FULL_ON()
{
uint8_t i, j;
for (i = 0; i < 8; i++)
{
OLED_address(0, i);
for (j = 0; j < 128; j++)
{
OLED_WR_Byte(0xFF, OLED_DATA);
}
}
}
void OLED_FULL_OFF()
{
uint8_t i, j;
for (i = 0; i < 8; i++)
{
OLED_address(0, i);
for (j = 0; j < 128; j++)
{
OLED_WR_Byte(0x00, OLED_DATA);
}
}
}
//显示64*128的图像
void OLED_Display_128x64(uint8_t *dp)
{
uint8_t i, j;
for (i = 0; i < 8; i++)
{
OLED_address(0, i);
for (j = 0; j < 128; j++)
{
OLED_WR_Byte(*dp, OLED_DATA);
dp++;
}
}
}
void OLED_Display_64x64(uint8_t x, uint8_t y, uint8_t *dp)
{
uint8_t i, j;
for (j = 0; j < 8; j++)
{
OLED_address(x, y);
for (i = 0; i < 64; i++)
{
OLED_WR_Byte(*dp, OLED_DATA);
dp++;
}
y++;
}
}
//显示16*16的图像
void OLED_Display_16x16(uint8_t x, uint8_t y, uint8_t *dp)
{
uint8_t i, j;
for (j = 0; j < 2; j++)
{
OLED_address(x, y);
for (i = 0; i < 16; i++)
{
OLED_WR_Byte(*dp, OLED_DATA);
dp++;
}
y++;
}
}
//显示8*16的图像 8宽,16 高
void OLED_Display_8x16(uint8_t x, uint8_t y, uint8_t *dp)
{
uint8_t i, j;
for (j = 0; j < 2; j++)
{
OLED_address(x, y);
for (i = 0; i < 8; i++)
{
OLED_WR_Byte(*dp, OLED_DATA);
dp++;
}
y++;
}
}
void OLED_Display_16x8(uint8_t x, uint8_t y, uint8_t *dp)
{
uint8_t i, j;
OLED_address(x, y);
for (i = 0; i < 16; i++)
{
OLED_WR_Byte(*dp, OLED_DATA);
dp++;
}
}
//在指定位置显示一个字符,包括部分字符
// x:0~127
// y:0~63
// mode:0,反白显示;1,正常显示
// size:选择字体 8,16,32,48
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size)
{
unsigned char c = 0, i = 0;
c = chr - ' '; //得到偏移后的值
if (x > OLED_width - 1)
{
x = 0;
y = y + 2;
}
if (size == 16)
{
OLED_address(x, y);
for (i = 0; i < 8; i++)
OLED_WR_Byte(F8X16[c * 16 + i], OLED_DATA);
OLED_address(x, y + 1);
for (i = 0; i < 8; i++)
OLED_WR_Byte(F8X16[c * 16 + i + 8], OLED_DATA);
}
else if(size == 8)
{
OLED_address(x, y);
for (i = 0; i < 6; i++)
OLED_WR_Byte(F6x8[c][i], OLED_DATA);
}
else if (size==32)
{
OLED_address(x, y);
for ( i = 0; i < 16; i++)
{
OLED_WR_Byte(F16x32[c * 64 + i], OLED_DATA);
}
OLED_address(x, y + 1);
for (i = 0; i < 16; i++)
OLED_WR_Byte(F16x32[c * 64 + i + 16], OLED_DATA);
OLED_address(x, y + 2);
for (i = 0; i < 16; i++)
OLED_WR_Byte(F16x32[c * 64 + i + 32], OLED_DATA);
OLED_address(x, y + 3);
for (i = 0; i < 16; i++)
OLED_WR_Byte(F16x32[c * 64 + i + 48], OLED_DATA);
}
else if (size==48)
{
OLED_address(x, y);
for ( i = 0; i < 24; i++)
{
OLED_WR_Byte(F24x48[c * 144 + i], OLED_DATA);
}
OLED_address(x, y + 1);
for (i = 0; i < 24; i++)
OLED_WR_Byte(F24x48[c * 144 + i + 24], OLED_DATA);
OLED_address(x, y + 2);
for (i = 0; i < 24; i++)
OLED_WR_Byte(F24x48[c * 144 + i + 48], OLED_DATA);
OLED_address(x, y + 3);
for (i = 0; i < 24; i++)
OLED_WR_Byte(F24x48[c * 144 + i + 72], OLED_DATA);
OLED_address(x, y + 4);
for (i = 0; i < 24; i++)
OLED_WR_Byte(F24x48[c * 144 + i + 96], OLED_DATA);
OLED_address(x, y + 5);
for (i = 0; i < 24; i++)
OLED_WR_Byte(F24x48[c * 144 + i + 120], OLED_DATA);
}
}
void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *p, uint8_t size)
{
unsigned char j = 0;
while (p[j] != '\0')
{
OLED_ShowChar(x, y, p[j], size);
x += 8;
if (x > 120)
{
x = 0;
y += 2;
}
j++;
}
}
uint16_t oled_pow(uint8_t m, uint8_t n)
{
uint16_t result = 1;
while (n--)
result *= m;
return result;
}
void OLED_ShowNum(uint8_t x, uint8_t y, uint16_t num, uint8_t len, uint8_t size)
{
uint8_t t, temp;
uint8_t enshow = 0;
for (t = 0; t < len; t++)
{
temp = (num / oled_pow(10, len - t - 1)) % 10; //取第t位数字
if (enshow == 0 && t < (len - 1))
{ //如果字符串长度小于指定长度
if (temp == 0)
{
OLED_ShowChar(x + (size / 2) * t, y, ' ', size); //多出来的位用空格补齐
continue; //循环判断
}
else
enshow = 1; //直到有数字为止
}
OLED_ShowChar(x + (size / 2) * t, y, temp + '0', size); //然后以 ASSII的"0"为基准偏移。
}
}
void OLED_ShowCN(uint8_t x, uint8_t y, uint8_t size)
{
unsigned char wm = 0;
unsigned int adder = 32 * size;
OLED_address(x, y);
for (wm = 0; wm < 16; wm++)
{
OLED_WR_Byte(F16x16[adder], 1);
adder += 1;
}
OLED_address(x, y + 1);
for (wm = 0; wm < 16; wm++)
{
OLED_WR_Byte(F16x16[adder], 1);
adder += 1;
}
}
//16*16个像素点,分为两行显示,一行是16*8
void OLED_ShowCN_one(uint8_t x, uint8_t y, uint8_t *p)
{
unsigned char wm = 0;
OLED_address(x, y);
for (wm = 0; wm < 16; wm++)
{
OLED_WR_Byte(p[wm], 1);
}
OLED_address(x, y + 1);
for (wm ; wm < 32; wm++)
{
OLED_WR_Byte(p[wm], 1);
}
}
#endif
六、字符汉字显示(进阶版):
适用于硬件IIC或者时钟频率快的开发板。
范围:x取(0,128),y取(0,63)
优点:可以任意画图,如一个点,矩形 ,圆形等。
#if point_mode
uint8_t OLED_GRAM[128][8];
void OLED_Refresh(void)
{
uint8_t i, n;
for (i = 0; i < 8; i++)
{
OLED_WR_Byte(0xb0 + i, OLED_CMD);
OLED_WR_Byte(0x00, OLED_CMD);
OLED_WR_Byte(0x10, OLED_CMD);
I2C_Start();
Send_Byte(0x78);
I2C_WaitAck();
Send_Byte(0x40);
I2C_WaitAck();
for (n = 0; n < 128; n++)
{
Send_Byte(OLED_GRAM[n][i]);
I2C_WaitAck();
}
I2C_Stop();
}
}
void OLED_GFill(){
uint8_t i,j;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 128; j++)
{
OLED_GRAM[j][i]=0xFF;
}
}
OLED_Refresh();
}
void OLED_Clear(void)
{
uint8_t i, n;
for (i = 0; i < 8; i++)
{
for (n = 0; n < 128; n++)
{
OLED_GRAM[n][i] = 0;
}
}
OLED_Refresh(); //¸üÐÂÏÔʾ
}
void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t t)
{
uint8_t i, m, n;
i = y / 8;
m = y % 8;
n = 1 << m;
if (t)
{
OLED_GRAM[x][i] |= n;
}
else
{
OLED_GRAM[x][i] = ~OLED_GRAM[x][i];
OLED_GRAM[x][i] |= n;
OLED_GRAM[x][i] = ~OLED_GRAM[x][i];
}
}
void OLED_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode)
{
uint16_t t;
int xerr = 0, yerr = 0, delta_x, delta_y, distance;
int incx, incy, uRow, uCol;
delta_x = x2 - x1; //¼ÆËã×ø±êÔöÁ¿
delta_y = y2 - y1;
uRow = x1; //»Ï߯ðµã×ø±ê
uCol = y1;
if (delta_x > 0)
incx = 1; //ÉèÖõ¥²½·½Ïò
else if (delta_x == 0)
incx = 0; //´¹Ö±Ïß
else
{
incx = -1;
delta_x = -delta_x;
}
if (delta_y > 0)
incy = 1;
else if (delta_y == 0)
incy = 0; //ˮƽÏß
else
{
incy = -1;
delta_y = -delta_x;
}
if (delta_x > delta_y)
distance = delta_x;
else
distance = delta_y;
for (t = 0; t < distance + 1; t++)
{
OLED_DrawPoint(uRow, uCol, mode); //»µã
xerr += delta_x;
yerr += delta_y;
if (xerr > distance)
{
xerr -= distance;
uRow += incx;
}
if (yerr > distance)
{
yerr -= distance;
uCol += incy;
}
}
OLED_Refresh();
}
void OLED_DrawCircle(uint8_t x, uint8_t y, uint8_t r)
{
int a, b, num;
a = 0;
b = r;
while (2 * b * b >= r * r)
{
OLED_DrawPoint(x + a, y - b, 1);
OLED_DrawPoint(x - a, y - b, 1);
OLED_DrawPoint(x - a, y + b, 1);
OLED_DrawPoint(x + a, y + b, 1);
OLED_DrawPoint(x + b, y + a, 1);
OLED_DrawPoint(x + b, y - a, 1);
OLED_DrawPoint(x - b, y - a, 1);
OLED_DrawPoint(x - b, y + a, 1);
a++;
num = (a * a + b * b) - r * r;
if (num > 0)
{
b--;
a--;
}
}
OLED_Refresh();
}
void OLED_G_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size1, uint8_t mode)
{
uint8_t i, m, temp, size2, chr1;
uint8_t x0 = x, y0 = y;
if (size1 == 8)
size2 = 6;
else
size2 = (size1 / 8 + ((size1 % 8) ? 1 : 0)) * (size1 / 2);
chr1 = chr - ' ';
for (i = 0; i < size2; i++)
{
if (size1 == 8)
{
temp = asc2_0806[chr1][i];
} //µ÷ÓÃ0806×ÖÌå
else if (size1 == 12)
{
temp = asc2_1206[chr1][i];
} //µ÷ÓÃ1206×ÖÌå
else if (size1 == 16)
{
temp = asc2_1608[chr1][i];
} //µ÷ÓÃ1608×ÖÌå
else if (size1 == 24)
{
temp = asc2_2412[chr1][i];
} //µ÷ÓÃ2412×ÖÌå
else
return;
for (m = 0; m < 8; m++)
{
if (temp & 0x01)
OLED_DrawPoint(x, y, mode);
else
OLED_DrawPoint(x, y, !mode);
temp >>= 1;
y++;
}
x++;
if ((size1 != 8) && ((x - x0) == size1 / 2))
{
x = x0;
y0 = y0 + 8;
}
y = y0;
}
}
void OLED_G_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_t size1, uint8_t mode)
{
while ((*chr >= ' ') && (*chr <= '~')) //ÅжÏÊDz»ÊÇ·Ç·¨×Ö·û!
{
OLED_ShowChar(x, y, *chr, size1, mode);
if (size1 == 8)
x += 6;
else
x += size1 / 2;
chr++;
}
OLED_Refresh();
}
// m^n
uint32_t OLED_Pow(uint8_t m, uint8_t n)
{
uint32_t result = 1;
while (n--)
{
result *= m;
}
return result;
}
void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size1, uint8_t mode)
{
uint8_t t, temp, m = 0;
if (size1 == 8)
m = 2;
for (t = 0; t < len; t++)
{
temp = (num / OLED_Pow(10, len - t - 1)) % 10;
if (temp == 0)
{
OLED_ShowChar(x + (size1 / 2 + m) * t, y, '0', size1, mode);
}
else
{
OLED_ShowChar(x + (size1 / 2 + m) * t, y, temp + '0', size1, mode);
}
}
OLED_Refresh();
}
void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t num, uint8_t size1, uint8_t mode)
{
uint8_t m, temp;
uint8_t x0 = x, y0 = y;
uint16_t i, size3 = (size1 / 8 + ((size1 % 8) ? 1 : 0)) * size1;
for (i = 0; i < size3; i++)
{
if (size1 == 16)
{
temp = Hzk1[num][i];
} //µ÷ÓÃ16*16×ÖÌå
else if (size1 == 24)
{
temp = Hzk2[num][i];
} //µ÷ÓÃ24*24×ÖÌå
else if (size1 == 32)
{
temp = Hzk3[num][i];
} //µ÷ÓÃ32*32×ÖÌå
else if (size1 == 64)
{
temp = Hzk4[num][i];
} //µ÷ÓÃ64*64×ÖÌå
else
return;
for (m = 0; m < 8; m++)
{
if (temp & 0x01)
OLED_DrawPoint(x, y, mode);
else
OLED_DrawPoint(x, y, !mode);
temp >>= 1;
y++;
}
x++;
if ((x - x0) == size1)
{
x = x0;
y0 = y0 + 8;
}
y = y0;
}
OLED_Refresh();
}
void OLED_ScrollDisplay(uint8_t num, uint8_t space, uint8_t mode)
{
uint8_t i, n, t = 0, m = 0, r;
while (1)
{
if (m == 0)
{
OLED_ShowChinese(128, 24, t, 16, mode);
t++;
}
if (t == num)
{
for (r = 0; r < 16 * space; r++)
{
for (i = 1; i < 144; i++)
{
for (n = 0; n < 8; n++)
{
OLED_GRAM[i - 1][n] = OLED_GRAM[i][n];
}
}
OLED_Refresh();
}
t = 0;
}
m++;
if (m == 16)
{
m = 0;
}
for (i = 1; i < 144; i++)
{
for (n = 0; n < 8; n++)
{
OLED_GRAM[i - 1][n] = OLED_GRAM[i][n];
}
}
OLED_Refresh();
}
}
void OLED_ShowPicture(uint8_t x, uint8_t y, uint8_t sizex, uint8_t sizey, uint8_t BMP[], uint8_t mode)
{
uint16_t j = 0;
uint8_t i, n, temp, m;
uint8_t x0 = x, y0 = y;
sizey = sizey / 8 + ((sizey % 8) ? 1 : 0);
for (n = 0; n < sizey; n++)
{
for (i = 0; i < sizex; i++)
{
temp = BMP[j];
j++;
for (m = 0; m < 8; m++)
{
if (temp & 0x01)
OLED_DrawPoint(x, y, mode);
else
OLED_DrawPoint(x, y, !mode);
temp >>= 1;
y++;
}
x++;
if ((x - x0) == sizex)
{
x = x0;
y0 = y0 + 8;
}
y = y0;
}
}
OLED_Refresh();
}
#endif