- void OLED_GPIO_Init(void)
- {
- GPIO_Config_T configStruct;
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOD);
- GPIO_ConfigStructInit(&configStruct);
- configStruct.pin = SDA_PIN | SCL_PIN;
- configStruct.mode = GPIO_MODE_OUT;
- configStruct.speed = GPIO_SPEED_50MHz;
- GPIO_Config(SDA_PORT, &configStruct);
- GPIO_SetBit(SDA_PORT, SDA_PIN);
- GPIO_SetBit(SCL_PORT, SCL_PIN);
- }
设置输入和输出方向
- void SDA2_OUT()
- {
- GPIO_Config_T configStruct;
- GPIO_ConfigStructInit(&configStruct);
- configStruct.pin = SDA_PIN;
- configStruct.mode = GPIO_MODE_OUT;
- configStruct.speed = GPIO_SPEED_50MHz;
- GPIO_Config(SDA_PORT, &configStruct);
- }
- void SDA2_IN()
- {
- GPIO_Config_T configStruct;
- GPIO_ConfigStructInit(&configStruct);
- configStruct.pin = SDA_PIN;
- configStruct.mode = GPIO_MODE_IN;
- configStruct.pupd = GPIO_PUPD_UP;
- GPIO_Config(SDA_PORT, &configStruct);
- }
接着就是IIC的开始、结束、ACK、写入一个字节
- //开始信号
- void IIC2_Start(void)
- {
- SDA2_OUT();
- GPIO_SetBit(SDA_PORT, SDA_PIN);
- GPIO_SetBit(SCL_PORT, SCL_PIN);
- Delay_us(2);
- GPIO_ResetBit(SDA_PORT, SDA_PIN);
- Delay_us(2);
- GPIO_ResetBit(SCL_PORT, SCL_PIN);
- Delay_us(2);
- }
- void IIC2_Stop(void)
- {
- GPIO_SetBit(SCL_PORT, SCL_PIN);
- GPIO_ResetBit(SDA_PORT, SDA_PIN);
- Delay_us(2);
- GPIO_SetBit(SDA_PORT, SDA_PIN);
- Delay_us(2);
- }
- /*
- * 返回1--应答出错
- * 放回0--应答正确
- */
- u8 IIC_Wait_Ask(void)
- {
- int count=0;
- SDA2_IN();
- GPIO_SetBit(SCL_PORT, SCL_PIN);
- Delay_us(20);
- while(GPIO_ReadInputBit(SDA_PORT, SDA_PIN))
- {
- count++;
- if(count>250)
- {
- IIC2_Stop();
- return 1;
- }
- }
- GPIO_ResetBit(SCL_PORT, SCL_PIN);
- Delay_us(2);
- return 0;
- }
- //写一个字节
- void IIC_WriteByte(u8 data)
- {
- u8 i;
- SDA2_OUT();
- for(i=0;i<8;i++)
- {
- GPIO_ResetBit(SCL_PORT, SCL_PIN);
- Delay_us(2);
- if(data & 0x80) //MSB,从高位开始一位一位传输
- GPIO_SetBit(SDA_PORT, SDA_PIN);
- else
- GPIO_ResetBit(SDA_PORT, SDA_PIN);
- GPIO_SetBit(SCL_PORT, SCL_PIN);
- Delay_us(2);
- GPIO_ResetBit(SCL_PORT, SCL_PIN);
- data<<=1;
- }
- }
然后开始OLED的驱动
- void WriteCmd(u8 command)
- {
- IIC2_Start();
- IIC_WriteByte(0x78);//OLED地址
- IIC_Wait_Ask();
- IIC_WriteByte(0x00);//寄存器地址
- IIC_Wait_Ask();
- IIC_WriteByte(command);
- IIC_Wait_Ask();
- IIC2_Stop();
- }
- void WriteDat(u8 data)
- {
- IIC2_Start();
- IIC_WriteByte(0x78);//OLED地址
- IIC_Wait_Ask();
- IIC_WriteByte(0x40);//寄存器地址
- IIC_Wait_Ask();
- IIC_WriteByte(data);
- IIC_Wait_Ask();
- IIC2_Stop();
- }
- void OLED_Init(void)
- {
-
- Delay_ms(100); //这里的延时很重要
- WriteCmd(0xAE); //display off
- WriteCmd(0x20); //Set Memory Addressing Mode
- WriteCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
- WriteCmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7
- WriteCmd(0xc8); //Set COM Output Scan Direction
- WriteCmd(0x00); //---set low column address
- WriteCmd(0x10); //---set high column address
- WriteCmd(0x40); //--set start line address
- WriteCmd(0x81); //--set contrast control register
- WriteCmd(0xff); //???? 0x00~0xff
- WriteCmd(0xa1); //--set segment re-map 0 to 127
- WriteCmd(0xa6); //--set normal display
- WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
- WriteCmd(0x3F); //
- WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
- WriteCmd(0xd3); //-set display offset
- WriteCmd(0x00); //-not offset
- WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
- WriteCmd(0xf0); //--set divide ratio
- WriteCmd(0xd9); //--set pre-charge period
- WriteCmd(0x22); //
- WriteCmd(0xda); //--set com pins hardware configuration
- WriteCmd(0x12);
- WriteCmd(0xdb); //--set vcomh
- WriteCmd(0x20); //0x20,0.77xVcc
- WriteCmd(0x8d); //--set DC-DC enable
- WriteCmd(0x14); //
- WriteCmd(0xaf); //--turn on oled panel
- OLED_CLS();
- }
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] OLED_ON,将OLED从休眠中唤醒
- * @param 无
- * @retval 无
- */
- void OLED_ON(void)
- {
- WriteCmd(0X8D); //设置电荷泵
- WriteCmd(0X14); //开启电荷泵
- WriteCmd(0XAF); //OLED唤醒
- }
- /**
- * @brief OLED_SetPos,设置光标
- * @param x,光标x位置
- * y,光标y位置
- * @retval 无
- */
- void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标
- {
- WriteCmd(0xb0+y);
- WriteCmd(((x&0xf0)>>4)|0x10);
- WriteCmd((x&0x0f)|0x01);
- }
- /**
- * @brief OLED_Fill,填充整个屏幕
- * @param fill_Data:要填充的数据
- * @retval 无
- */
- void OLED_Fill(unsigned char fill_Data)//全屏填充
- {
- unsigned char m,n;
- for(m=0;m<8;m++)
- {
- WriteCmd(0xb0+m); //page0-page1
- WriteCmd(0x00); //low column start address
- WriteCmd(0x10); //high column start address
- for(n=0;n<128;n++)
- {
- WriteDat(fill_Data);
- }
- }
- }
- void OLED_CLS(void)//清屏
- {
- OLED_Fill(0x00);
- }
- void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
- {
- unsigned char c = 0,i = 0,j = 0;
- switch(TextSize)
- {
- case 1:
- {
- while(ch[j] != '\0')
- {
- c = ch[j] - 32;
- if(x > 126)
- {
- x = 0;
- y++;
- }
- OLED_SetPos(x,y);
- for(i=0;i<6;i++)
- WriteDat(F6x8[c][i]);
- x += 6;
- j++;
- }
- }break;
- case 2:
- {
- while(ch[j] != '\0')
- {
- c = ch[j] - 32;
- if(x > 120)
- {
- x = 0;
- y++;
- }
- OLED_SetPos(x,y);
- for(i=0;i<8;i++)
- WriteDat(F8X16[c*16+i]);
- OLED_SetPos(x,y+1);
- for(i=0;i<8;i++)
- WriteDat(F8X16[c*16+i+8]);
- x += 8;
- j++;
- }
- }break;
- }
- }
OK,到这里驱动就算结束了,然后我们再main里写要显示的内容
- unsigned char name8[] = "Geehy";
- unsigned char name7[] = "BBS: 21ic.com";
- unsigned char name6[] = "Mode: IIC\0";
- unsigned char name5[] = "Drv: OLED\0";
-
- int main(void)
- {
- /* Set system interrupt priority grouping */
- NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_2);
- /* Init delay function */
- Delay_Init();
- /* Init LED */
- APM_LEDInit(LED2);
- APM_LEDInit(LED3);
- OLED_Init();
- OLED_CLS();
-
- OLED_ShowStr(40, 0, name8, 2);
- OLED_ShowStr(0, 2, name7, 2);
- OLED_ShowStr(0, 4, name6, 2);
- OLED_ShowStr(0, 6, name5, 2);
- while(1)
- {
- Delay_ms(500);
- GPIOE->ODATA ^= GPIO_PIN_5;
- GPIOE->ODATA ^= GPIO_PIN_6;
- }
- }
最后看效果图