打印
[活动]

【APM32F411V开发板测评】+IIC驱动OLED屏幕

[复制链接]
244|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
    收到极海的开发板,首先要驱动一下自己正在做的一个项目的外设,OLED屏幕显示!

   1、考虑到模块移植的通用性,所以选择了模拟IIC驱动
         GPIO初始化SDA和SCL引脚
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;
        }
}


     最后看效果图




32323微信图片_20240606163941.jpg (139.62 KB )

32323微信图片_20240606163941.jpg

使用特权

评论回复
沙发
weifeng90| | 2024-6-6 19:04 | 只看该作者
IIC通信速率有限,屏幕刷新有点慢。

使用特权

评论回复
板凳
星辰大海不退缩| | 2024-6-22 21:38 | 只看该作者
楼主可以更换一个SPI通信的屏幕

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:清智科技嵌入式工程师
简介:单片机嵌入式底层开发,汽车电子

44

主题

498

帖子

17

粉丝