南来之风 发表于 2024-12-23 13:24

【AT-START-L021测评】硬件I2C/IIC 驱动OLED

先看效果:



首先进行OLED初始化:
void OLED_Init(void)
{      
      delay_ms(1000);
      
      WriteCmd(0xAE);//--turn off oled panel
      WriteCmd(0x00);//---set low column address
      WriteCmd(0x10);//---set high column address
      WriteCmd(0x40);//--set start line addressSet Mapping RAM Display Start Line (0x00~0x3F)
      WriteCmd(0x81);//--set contrast control register
      WriteCmd(0xCF);// Set SEG Output Current Brightness
      WriteCmd(0xA1);//--Set SEG/Column Mapping   0xa0���ҷ��� 0xa1����
      WriteCmd(0xC8);//Set COM/Row Scan Direction   0xc0���·��� 0xc8����
      WriteCmd(0xA6);//--set normal display
      WriteCmd(0xA8);//--set multiplex ratio(1 to 64)
      WriteCmd(0x3f);//--1/64 duty
      WriteCmd(0xD3);//-set display offset      Shift Mapping RAM Counter (0x00~0x3F)
      WriteCmd(0x00);//-not offset
      WriteCmd(0xd5);//--set display clock divide ratio/oscillator frequency
      WriteCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
      WriteCmd(0xD9);//--set pre-charge period
      WriteCmd(0xF1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
      WriteCmd(0xDA);//--set com pins hardware configuration
      WriteCmd(0x12);
      WriteCmd(0xDB);//--set vcomh
      WriteCmd(0x40);//Set VCOM Deselect Level
      WriteCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
      WriteCmd(0x02);//
      WriteCmd(0x8D);//--set Charge Pump enable/disable
      WriteCmd(0x14);//--set(0x10) disable
      WriteCmd(0xA4);// Disable Entire Display On (0xa4/0xa5)
      WriteCmd(0xA6);// Disable Inverse Display On (0xa6/a7)
      OLED_Clear();
      WriteCmd(0xAF);      //Set display on added by sensoryoung
      delay_ms(200);
}

然后刷新屏幕:
void OLED_Refresh(void)
{
      uint8_t i,n;
      for(i=0;i<8;i++)
      {
                WriteCmd(0xb0+i);
                WriteCmd(0x00);
                WriteCmd(0x10);

                for(n=0;n<128;n++)
                {
                        WriteDat(OLED_GRAM);
                }
}
}这里有关键的两个函数:WriteCmd 与 WriteDat。实现如下:

/**************************************************************
         Prototype      : void WriteCmd(uint8_t IIC_Command)
         Parameters   : IIC_Command
         return                                        : none
         Description    : 写命令(通过HAL_I2C_WriteByte中的HAL_I2C_Master_Transmit
                      向0x00写入命令)
***************************************************************/
void WriteCmd(uint8_t IIC_Command)
{
      HAL_I2C_WriteByte(0x00, IIC_Command);
}

/**************************************************************
         Prototype      : void WriteDat(uint8_t IIC_Data)
         Parameters   : IIC_Data
         return                                        : none
         Description    : 写数据(通过HAL_I2C_WriteByte中的HAL_I2C_Master_Transmit
                      向0x40写入数据)
***************************************************************/
void WriteDat(uint8_t IIC_Data)
{
      HAL_I2C_WriteByte(0x40, IIC_Data);
在调用I2C模块向总线发送数据之前,封装了一下:

/***************************************************
    I2C总线传出数据函数:
                addr:    要写入的地址(OLED的地址一般为0x40;指令地址为0x00)
                data:    要写入的数据
***************************************************/
void HAL_I2C_WriteByte(uint8_t addr,uint8_t data)
{
      //uint8_t TxData = {addr,data};
      uint8_t TxData;
      TxData = addr;
      TxData = data;
if((i2c_status = i2c_master_transmit(&hi2cx, 0X78, TxData, 2, I2C_TIMEOUT)) != I2C_OK)
{
    error_handler(i2c_status);
}      
}实际效果还不错,完整代码如下:
/*Reference: https://blog.csdn.net/Reasally/article/details/126789505*/
#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"         

//For ARTEY ATL021
extern void error_handler(uint32_t error_code);
extern i2c_handle_type hi2cx;
extern i2c_status_type i2c_status;
#define I2C_TIMEOUT                      0xFFFFFFF

uint8_t OLED_GRAM;

//���Ժ���
void OLED_ColorTurn(uint8_t i)
{
      if(i==0)
                {
                        WriteCmd(0xA6);
                }
      if(i==1)
                {
                        WriteCmd(0xA7);
                }
}

//��Ļ��ת180��
void OLED_DisplayTurn(uint8_t i)
{
      if(i==0)
                {
                        WriteCmd(0xC8);
                        WriteCmd(0xA1);
                }
      if(i==1)
                {
                        WriteCmd(0xC0);
                        WriteCmd(0xA0);
                }
}

//��ʱ
void IIC_delay(void)
{
      uint16_t t=300;
      while(t--);
}

/***************************************************
    I2C总线传出数据函数:
                addr:    要写入的地址(OLED的地址一般为0x40;指令地址为0x00)
                data:    要写入的数据
***************************************************/
void HAL_I2C_WriteByte(uint8_t addr,uint8_t data)
{
      //uint8_t TxData = {addr,data};
      uint8_t TxData;
      TxData = addr;
      TxData = data;
if((i2c_status = i2c_master_transmit(&hi2cx, 0X78, TxData, 2, I2C_TIMEOUT)) != I2C_OK)
{
    error_handler(i2c_status);
}      
}

/**************************************************************
         Prototype      : void WriteCmd(uint8_t IIC_Command)
         Parameters   : IIC_Command
         return                                        : none
         Description    : 写命令(通过HAL_I2C_WriteByte中的HAL_I2C_Master_Transmit
                      向0x00写入命令)
***************************************************************/
void WriteCmd(uint8_t IIC_Command)
{
      HAL_I2C_WriteByte(0x00, IIC_Command);
}

/**************************************************************
         Prototype      : void WriteDat(uint8_t IIC_Data)
         Parameters   : IIC_Data
         return                                        : none
         Description    : 写数据(通过HAL_I2C_WriteByte中的HAL_I2C_Master_Transmit
                      向0x40写入数据)
***************************************************************/
void WriteDat(uint8_t IIC_Data)
{
      HAL_I2C_WriteByte(0x40, IIC_Data);
}


//����һ���ֽ�
//mode:����/�����־ 0,��ʾ����;1,��ʾ����;
void OLED_WR_Byte(uint8_t dat,uint8_t mode)
{
      
      if(mode){
                //Send_Byte(0x40);
                WriteDat(dat);
      }
      else{
                //Send_Byte(0x00);
                WriteCmd(dat);
      }
    //Send_Byte(dat);
    //I2C_Stop();
}



//����OLED��ʾ
void OLED_DisPlay_On(void)
{
      WriteCmd(0x8D);
      WriteCmd(0x14);
      WriteCmd(0xAF);
}

//�ر�OLED��ʾ
void OLED_DisPlay_Off(void)
{
      WriteCmd(0x8D);
      WriteCmd(0x10);
      WriteCmd(0xAE);
}

//�����Դ浽OLED      
void OLED_Refresh(void)
{
      uint8_t i,n;
      for(i=0;i<8;i++)
      {
                WriteCmd(0xb0+i);
                WriteCmd(0x00);
                WriteCmd(0x10);

                for(n=0;n<128;n++)
                {
                        WriteDat(OLED_GRAM);
                }
}
}
//��������
void OLED_Clear(void)
{
      uint8_t i,n;
      for(i=0;i<8;i++)
      {
         for(n=0;n<128;n++)
                        {
                         OLED_GRAM=0;//�����������
                        }
}
}

//����
//x:0~127
//y:0~63
//t:1 ��� 0,���      
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|=n;}
      else
      {
                OLED_GRAM=~OLED_GRAM;
                OLED_GRAM|=n;
                OLED_GRAM=~OLED_GRAM;
      }
}

//����
//x1,y1:�������
//x2,y2:��������
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;
                }
      }
}
//x,y:Բ������
//r:Բ�İ뾶
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--;
      }
    }
}



//��ָ��λ����ʾһ���ַ�,���������ַ�
//x:0~127
//y:0~63
//size1:ѡ������ 6x8/6x12/8x16/12x24
//mode:0,��ɫ��ʾ;1,������ʾ
void OLED_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;} //����0806����
                else if(size1==12)
      {temp=asc2_1206;} //����1206����
                else if(size1==16)
      {temp=asc2_1608;} //����1608����
                else if(size1==24)
      {temp=asc2_2412;} //����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;
}
}


//��ʾ�ַ���
//x,y:�������
//size1:�����С
//*chr:�ַ�����ʼ��ַ
//mode:0,��ɫ��ʾ;1,������ʾ
void OLED_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++;
}
}

//m^n
uint32_t OLED_Pow(uint8_t m,uint8_t n)
{
      uint32_t result=1;
      while(n--)
      {
          result*=m;
      }
      return result;
}

//��ʾ����
//x,y :�������
//num :Ҫ��ʾ������
//len :���ֵ�λ��
//size:�����С
//mode:0,��ɫ��ʾ;1,������ʾ
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);
                        }
}
}

//��ʾ����
//x,y:�������
//num:���ֶ�Ӧ�����
//mode:0,��ɫ��ʾ;1,������ʾ
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;}//����16*16����
                else if(size1==24)
                              {temp=Hzk2;}//����24*24����
                else if(size1==32)      
                              {temp=Hzk3;}//����32*32����
                else if(size1==64)
                              {temp=Hzk4;}//����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;
      }
}

//num ��ʾ���ֵĸ���
//space ÿһ����ʾ�ļ��
//mode:0,��ɫ��ʾ;1,������ʾ
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); //д��һ�����ֱ�����OLED_GRAM[][]������
                        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=OLED_GRAM;
                                                      }
                                                }
         OLED_Refresh();
                                 }
      t=0;
      }
                m++;
                if(m==16){m=0;}
                for(i=1;i<144;i++)   //ʵ������
                {
                        for(n=0;n<8;n++)
                        {
                              OLED_GRAM=OLED_GRAM;
                        }
                }
                OLED_Refresh();
      }
}

//x,y���������
//sizex,sizey,ͼƬ����
//BMP[]��Ҫд���ͼƬ����
//mode:0,��ɫ��ʾ;1,������ʾ
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++;
                              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�ij�ʼ��
void OLED_Init(void)
{      
      delay_ms(1000);
      
      WriteCmd(0xAE);//--turn off oled panel
      WriteCmd(0x00);//---set low column address
      WriteCmd(0x10);//---set high column address
      WriteCmd(0x40);//--set start line addressSet Mapping RAM Display Start Line (0x00~0x3F)
      WriteCmd(0x81);//--set contrast control register
      WriteCmd(0xCF);// Set SEG Output Current Brightness
      WriteCmd(0xA1);//--Set SEG/Column Mapping   0xa0���ҷ��� 0xa1����
      WriteCmd(0xC8);//Set COM/Row Scan Direction   0xc0���·��� 0xc8����
      WriteCmd(0xA6);//--set normal display
      WriteCmd(0xA8);//--set multiplex ratio(1 to 64)
      WriteCmd(0x3f);//--1/64 duty
      WriteCmd(0xD3);//-set display offset      Shift Mapping RAM Counter (0x00~0x3F)
      WriteCmd(0x00);//-not offset
      WriteCmd(0xd5);//--set display clock divide ratio/oscillator frequency
      WriteCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
      WriteCmd(0xD9);//--set pre-charge period
      WriteCmd(0xF1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
      WriteCmd(0xDA);//--set com pins hardware configuration
      WriteCmd(0x12);
      WriteCmd(0xDB);//--set vcomh
      WriteCmd(0x40);//Set VCOM Deselect Level
      WriteCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
      WriteCmd(0x02);//
      WriteCmd(0x8D);//--set Charge Pump enable/disable
      WriteCmd(0x14);//--set(0x10) disable
      WriteCmd(0xA4);// Disable Entire Display On (0xa4/0xa5)
      WriteCmd(0xA6);// Disable Inverse Display On (0xa6/a7)
      OLED_Clear();
      WriteCmd(0xAF);      //Set display on added by sensoryoung
      delay_ms(200);
}




页: [1]
查看完整版本: 【AT-START-L021测评】硬件I2C/IIC 驱动OLED