看完网友在STM32上驱动0.96寸4PIN IIC OLED显示字符、数字、字符串、中文的讲解及代码后,现在将其移植了MSP430G2553/MSP430F552上,代码在原来的基础上做了一丢丢修改。原文链接:https://www.cnblogs.com/dragonet-Z/p/14689345.html


oled.h的代码如下:
/*
  • * 代码贡献作者:Dragonet-Z
  • * 使用方式:
  • *      在本 oled.h 的宏定义出修改对应的管脚;
  • *      main()函数里面调用OLED_Init()函数;
  • *      英文字符显示:OLED_ShowChar( 0,4,'O');
  • *      英文字符串显示:OLED_ShowString(0,0,"HELLO MSP430");
  • *      数字显示:OLED_ShowNum( 0,6,20,2);
  • *      中文显示:OLED_ShowCHinese( 0,2,0); 在显示中文的时候,要在 oledfont.h 里面去修改对应的字库内容
  • */
  • #ifndef USER_OLED_H_
  • #define USER_OLED_H_
  • #include <msp430.h>
  • /*--------------------IIC引脚定义--------------------------*/
  • /*----------------需要改成自己实际连接的管脚--------------------*/
  • #define OLED_SCL_PORT_OUT P2OUT
  • #define OLED_SDA_PORT_OUT P2OUT
  • #define OLED_SCL_PORT_DIR P2DIR
  • #define OLED_SDA_PORT_DIR P2DIR
  • #define OLED_SCL_PIN_NUM  BIT5
  • #define OLED_SDA_PIN_BUM  BIT4
  • /*--------------从使用的角度出发,以下代码不需要修改---------------*/
  • /*--------------从使用的角度出发,以下代码不需要修改---------------*/
  • /*--------------从使用的角度出发,以下代码不需要修改---------------*/
  • /*--------------------引脚定义--------------------------*/
  • #define OLED_SCLK_Clr() OLED_SCL_PORT_OUT &=~ OLED_SCL_PIN_NUM  //SCL
  • #define OLED_SCLK_Set() OLED_SCL_PORT_OUT |=  OLED_SCL_PIN_NUM
  • #define OLED_SDIN_Clr() OLED_SDA_PORT_OUT &=~ OLED_SDA_PIN_BUM  //SDA
  • #define OLED_SDIN_Set() OLED_SDA_PORT_OUT |=  OLED_SDA_PIN_BUM
  • #define OLED_SCL_PIN_DIR() OLED_SCL_PORT_DIR |= OLED_SCL_PIN_NUM;   //SCL-DIR
  • #define OLED_SDA_PIN_DIR() OLED_SDA_PORT_DIR |= OLED_SDA_PIN_BUM;   //SDA-DIR
  • /*definition--------------------------------------------*/
  • #define OLED_CMD    0       // 写命令
  • #define OLED_DATA   1       // 写数据
  • #define SIZE        16      // 显示字符的大小
  • #define Max_Column  128     // 最大列数
  • #define Max_Row     64      // 最大行数
  • #define X_WIDTH     128     // X轴的宽度
  • #define Y_WIDTH     64      // Y轴的宽度
  • #define IIC_ACK     0       // 应答
  • #define IIC_NO_ACK  1       // 不应答
  • /*-----------------声明函数-----------------------------*/
  • void OLED_Display_On(void);     //开显示函数
  • void OLED_Display_Off(void);    //关显示函数
  • void OLED_Init(void);           //OLED初始化函数
  • void OLED_Clear(void);          //清屏函数
  • void OLED_ShowChar(unsigned char x,unsigned char y,unsigned char chr);      //显示字符函数
  • void OLED_ShowNum(unsigned char x,unsigned char y,unsigned int num,unsigned char len);  //在指定的位置,显示一个指定数的长度大小函数
  • void OLED_ShowString(unsigned char x,unsigned char y, unsigned char *p);    //在指定位置开始显示字符串函数
  • void OLED_Set_Pos(unsigned char x, unsigned char y);        //画点函数
  • void OLED_ShowCHinese(unsigned char x,unsigned char y,unsigned char no);    //声明在指定位置显示汉字函数
  • void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[]); //显示图片函数
  • void OLED_Scroll(void);         //滚动函数
  • #endif /* USER_OLED_H_ */
  • 复制代码
    OLED.C代码
    /*
  • * 代码贡献作者:Dragonet-Z
  • */
  • /*--------------从使用的角度出发,以下代码不需要修改,直接调用对应的显示函数即可---------------*/
  • /*--------------从使用的角度出发,以下代码不需要修改,直接调用对应的显示函数即可---------------*/
  • /*--------------从使用的角度出发,以下代码不需要修改,直接调用对应的显示函数即可---------------*/
  • /*includes----------------------------------------------*/
  • #include "oled.h"
  • #include "oledfont.h"
  • /*definition--------------------------------------------*/
  • static void OLED_IIC_Start(void);
  • static void OLED_IIC_Stop(void);
  • static void Write_IIC_Command(unsigned char IIC_Command);
  • static void Write_IIC_Data(unsigned char IIC_Data);
  • static void Write_IIC_Byte(unsigned char IIC_Byte);
  • static void IIC_Wait_Ack(void);
  • //static void delay(unsigned char num);
  • ///*
  • // * @brief           延迟1us
  • // * @param           无
  • // * @retval      无
  • // */
  • //static void delay(unsigned char num)
  • //{
  • //    unsigned char i = 10;
  • //    while(num--)
  • //    {
  • //        while(i--);
  • //    }
  • //}
  • /*
  • * @brief           ms延迟函数
  • * @param           无
  • * @retval      无
  • */
  • static void delay_ms(unsigned int ms)//延迟函数,MS级别
  • {
  •     unsigned int x,y;
  •     for(x = ms;x>0;x--)
  • {
  •         for(y = 12000;y>0;y--);
  • }
  • }
  • /*
  • * @brief           模拟IIC起始信号
  • * @param           无
  • * @retval      无
  • */
  • static void OLED_IIC_Start(void)
  • {
  •     OLED_SCLK_Set();
  •     OLED_SDIN_Set();
  •     OLED_SDIN_Clr();
  •     OLED_SCLK_Clr();
  • }
  • /*
  • * @brief           模拟IIC停止信号
  • * @param           无
  • * @retval      无
  • */
  • static void OLED_IIC_Stop(void)
  • {
  •     OLED_SCLK_Set() ;
  • //  OLED_SCLK_Clr();
  •     OLED_SDIN_Clr();
  •     OLED_SDIN_Set();
  • }
  • /*
  • * @brief           模拟IIC读取从机应答信号
  • * @param           无
  • * @retval      无
  • */
  • static void IIC_Wait_Ack(void)
  • {
  •     OLED_SCLK_Set() ;
  •     OLED_SCLK_Clr();
  • }
  • /*
  • * @brief           模拟IIC主机发送应答信号
  • * @param           无
  • * @retval      无
  • */
  • // static void IIC_Send_Ack(unsigned char ack)
  • // {
  • //  OLED_SCLK_Clr();    //时钟线置低
  • //  delay(1);   //延迟1us
  • //  if(ack == IIC_ACK)  //根据情况发送应答/不应答
  • //      OLED_SDIN_Clr();    //应答
  • //  else
  • //      OLED_SDIN_Set();    //不应答
  • //  delay(1);   //延迟1us
  • //  OLED_SCLK_Set();    //时钟线置高,发送应答/不应答信号
  • //  delay(1);   //延迟1us
  • //  OLED_SCLK_Clr();    //时钟线置低
  • //  delay(1);   //延迟1us
  • // }
  • /*
  • * @brief           IIC写入一个字节
  • * @param           IIC_Byte:写入的字节
  • * @retval      无
  • */
  • static void Write_IIC_Byte(unsigned char IIC_Byte)
  • {
  •     unsigned char i;
  •     unsigned char m,da;
  •     da=IIC_Byte;
  •     OLED_SCLK_Clr();
  •     for(i=0;i<8;i++)
  •     {
  •             m=da;
  •         //  OLED_SCLK_Clr();
  •         m=m&0x80;
  •         if(m==0x80)
  •         {OLED_SDIN_Set();}
  •         else OLED_SDIN_Clr();
  •             da=da<<1;
  •         OLED_SCLK_Set();
  •         OLED_SCLK_Clr();
  •     }
  • }
  • /*
  • * @brief           IIC写读取一个字节
  • * @param           ack:应答/不应答
  • * @retval      无
  • */
  • // static unsigned char Read_IIC_Byte(unsigned char ack)
  • // {
  • //  unsigned char data = 0;  //定义变量
  • //  unsigned char i;  //定义变量
  • //  OLED_SCLK_Clr();    //时钟线置低,为传输数据做准备
  • //  delay(1);   //延迟1us
  • //  OLED_SDIN_Set();
  • //  for(i=0;i<8;i++) //for循环8次
  • //  {
  • //      OLED_SCLK_Set();    //时钟线置高,读取数据
  • //      delay(1);   //延迟1us
  • //      data <<= 1; //左移1位
  • //      if(OLED_READ_SDIN())    //读取最高位
  • //          data |= 0x01;   //读到高位位1
  • //      else
  • //          data &= 0xfe;   //读到高位为0
  • //      OLED_SCLK_Clr();    //时钟线置低,准备读取下一个数据
  • //      delay(1);   //延迟1us
  • //  }
  • //  IIC_Send_Ack(ack);  //发送应答/不应答
  • //  return data;    //返回读取到的数据
  • // }
  • /*
  • * @brief           IIC写入命令
  • * @param           IIC_Command:写入的命令
  • * @retval      无
  • */
  • static void Write_IIC_Command(unsigned char IIC_Command)
  • {
  •     OLED_IIC_Start();
  •     Write_IIC_Byte(0x78);            //Slave address,SA0=0
  •      IIC_Wait_Ack();
  •     Write_IIC_Byte(0x00);            //write command
  •      IIC_Wait_Ack();
  •     Write_IIC_Byte(IIC_Command);
  •      IIC_Wait_Ack();
  •      OLED_IIC_Stop();
  • }
  • /*
  • * @brief           IIC写入数据
  • * @param           IIC_Data:数据
  • * @retval      无
  • */
  • static void Write_IIC_Data(unsigned char IIC_Data)
  • {
  •     OLED_IIC_Start();
  •     Write_IIC_Byte(0x78);            //D/C#=0; R/W#=0
  •      IIC_Wait_Ack();
  •     Write_IIC_Byte(0x40);            //write data
  •      IIC_Wait_Ack();
  •     Write_IIC_Byte(IIC_Data);
  •      IIC_Wait_Ack();
  •      OLED_IIC_Stop();
  • }
  • /*
  • * @brief           对OLED写入一个字节
  • * @param           dat:数据
  • *      cmd:1,写诶数据;0,写入命令
  • * @retval      无
  • */
  • static void OLED_WR_Byte(unsigned char dat,unsigned char cmd)
  • {
  •     if(cmd)
  •       {
  •        Write_IIC_Data(dat); //写入数据
  •       }
  •     else {
  •        Write_IIC_Command(dat); //写入命令
  •     }
  • }
  • /*
  • * @brief           设置数据写入的起始行、列
  • * @param           x: 列的起始低地址与起始高地址;0x00~0x0f:设置起始列低地址(在页寻址模式);
  • *      0x10~0x1f:设置起始列高地址(在页寻址模式)
  • *      y:起始页地址 0~7
  • * @retval      无
  • */
  • void OLED_Set_Pos(unsigned char x, unsigned char y)
  • {
  •     OLED_WR_Byte(0xb0+y,OLED_CMD);//写入页地址
  •     OLED_WR_Byte((x&0x0f),OLED_CMD);  //写入列的地址  低半字节
  •     OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);//写入列的地址 高半字节
  • }
  • /*
  • * @brief           开显示
  • * @param           无
  • * @retval      无
  • */
  • void OLED_Display_On(void)
  • {
  •     OLED_WR_Byte(0X8D,OLED_CMD);  //设置OLED电荷泵
  •     OLED_WR_Byte(0X14,OLED_CMD);  //使能,开
  •     OLED_WR_Byte(0XAF,OLED_CMD);  //开显示
  • }
  • /*
  • * @brief           关显示
  • * @param           无
  • * @retval      无
  • */
  • void OLED_Display_Off(void)
  • {
  •     OLED_WR_Byte(0XAE,OLED_CMD);  //关显示
  •     OLED_WR_Byte(0X8D,OLED_CMD);  //设置OLED电荷泵
  •     OLED_WR_Byte(0X10,OLED_CMD);  //失能,关
  • }
  • /*
  • * @brief           清屏
  • * @param           无
  • * @retval      无
  • */
  • void OLED_Clear(void)
  • {
  •     unsigned char i,n;          //定义变量
  •     for(i=0;i<8;i++)
  •     {
  •         OLED_WR_Byte (0xb0+i,OLED_CMD);    //从0~7页依次写入
  •         OLED_WR_Byte (0x00,OLED_CMD);      //列低地址
  •         OLED_WR_Byte (0x10,OLED_CMD);      //列高地址
  •         for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); //写入 0 清屏
  •     }
  • }
  • /*
  • * @brief           显示一个字符
  • * @param           x:起始列
  • *      y:起始页,SIZE = 16占两页;SIZE = 12占1页
  • *      chr:字符
  • * @retval      无
  • */
  • void OLED_ShowChar(unsigned char x,unsigned char y,unsigned char chr)
  • {
  •     unsigned char c=0,i=0;
  •         c=chr-' '; //获取字符的偏移量
  •         if(x>Max_Column-1){x=0;y=y+2;} //如果列数超出了范围,就从下2页的第0列开始
  •         if(SIZE ==16) //字符大小如果为 16 = 8*16
  •             {
  •                 OLED_Set_Pos(x,y);  //从x y 开始画点
  •                 for(i=0;i<8;i++)  //循环8次 占8列
  •                 OLED_WR_Byte(F8X16[c*16+i],OLED_DATA); //找出字符 c 的数组位置,先在第一页把列画完
  •                 OLED_Set_Pos(x,y+1); //页数加1
  •                 for(i=0;i<8;i++)  //循环8次
  •                 OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA); //把第二页的列数画完
  •             }
  •         else    //字符大小为 6 = 6*8
  •             {
  •                 OLED_Set_Pos(x,y+1); //一页就可以画完
  •                 for(i=0;i<6;i++) //循环6次 ,占6列
  •                 OLED_WR_Byte(F6x8[c][i],OLED_DATA); //把字符画完
  •             }
  • }
  • /*
  • * @brief           计算m^n
  • * @param           m:输入的一个数
  • *      n:输入数的次方
  • * @retval      result:一个数的n次方
  • */
  • static unsigned int oled_pow(unsigned char m,unsigned char n)
  • {
  •     unsigned int result=1;
  •     while(n--)result*=m;
  •     return result;
  • }
  • /*
  • * @brief           在指定的位置,显示一个指定长度大小的数
  • * @param           x:起始列
  • *      y:起始页
  • *      num:数字
  • *      len:数字的长度
  • * @retval      无
  • */
  • void OLED_ShowNum(unsigned char x,unsigned char y,unsigned int num,unsigned char len)
  • {
  •     unsigned char t,temp;  //定义变量
  •     unsigned char enshow=0;     //定义变量
  •     unsigned char size;
  •     size = len*8;
  •     for(t=0;t<len;t++)
  •     {
  •         temp=(num/oled_pow(10,len-t-1))%10;//取出输入数的每个位,由高到低
  •         if(enshow==0&&t<(len-1)) //enshow:是否为第一个数;t<(len-1):判断是否为最后一个数
  •         {
  •             if(temp==0) //如果该数为0
  •             {
  •                 OLED_ShowChar(x+(size/2)*t,y,' ');//显示 0 ;x+(size2/2)*t根据字体大小偏移的列数(8)
  •                 continue; //跳过剩下语句,继续重复循环(避免重复显示)
  •             }else enshow=1;
  •         }
  •         OLED_ShowChar(x+(size/2)*t,y,temp+'0'); //显示一个位;x+(size2/2)*t根据字体大小偏移的列数(8)
  •     }
  • }
  • /*
  • * @brief           显示字符串
  • * @param           x:起始列
  • *      y:起始页
  • *      *chr:第一个字符首地址
  • * @retval      无
  • */
  • void OLED_ShowString(unsigned char x,unsigned char y,unsigned char *chr)
  • {
  •     unsigned char j=0; //定义变量
  •     while (chr[j]!='\0') //如果不是最后一个字符
  •     {
  •         OLED_ShowChar(x,y,chr[j]); //显示字符
  •         x+=8; //列数加8 ,一个字符的列数占8
  •         if(x>=128){x=0;y+=2;} //如果x大于等于128,切换页,从该页的第一列显示
  •         j++; //下一个字符
  •     }
  • }
  • /*
  • * @brief           显示中文
  • * @param           x:起始列;一个字体占16列
  • *      y:起始页;一个字体占两页
  • *      no:字体的序号
  • * @retval      无
  • */
  • void OLED_ShowCHinese(unsigned char x,unsigned char y,unsigned char no)
  • {
  •     unsigned char t,adder=0; //定义变量
  •     OLED_Set_Pos(x,y);  //从 x y 开始画点,先画第一页
  •     for(t=0;t<16;t++) //循环16次,画第一页的16列
  •         {
  •             OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);//画no在数组位置的第一页16列的点
  •             adder+=1; //数组地址加1
  •         }
  •         OLED_Set_Pos(x,y+1); //画第二页
  •     for(t=0;t<16;t++)//循环16次,画第二页的16列
  •         {
  •             OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);//画no在数组位置的第二页16列的点
  •             adder+=1;//数组地址加1
  •         }
  • }
  • /*
  • * @brief           显示图片
  • * @param           x0:起始列地址
  • *      y0:起始页地址
  • *      x1:终止列地址
  • *      y1:终止页地址
  • *      BMP[]:存放图片代码的数组
  • * @retval      无
  • */
  • void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[])
  • {
  •     unsigned int j=0; //定义变量
  •     unsigned char x,y; //定义变量
  •     if(y1%8==0) y=y1/8;   //判断终止页是否为8的整数倍
  •      else y=y1/8+1;
  •         for(y=y0;y<y1;y++) //从起始页开始,画到终止页
  •         {
  •             OLED_Set_Pos(x0,y); //在页的起始列开始画
  •             for(x=x0;x<x1;x++) //画x1 - x0 列
  •                 {
  •                     OLED_WR_Byte(BMP[j++],OLED_DATA);   //画图片的点
  •                 }
  •         }
  • }
  • /*
  • * @brief           OLED初始化函数
  • * @param           无
  • * @retval      无
  • */
  • void OLED_Init(void)
  • {
  •     OLED_SCL_PIN_DIR();
  •     OLED_SDA_PIN_DIR();
  •     delay_ms(200);  //延迟,由于单片机上电初始化比OLED快,所以必须加上延迟,等待OLED上复位完成
  •     OLED_WR_Byte(0xAE,OLED_CMD);    //关闭显示
  •     OLED_WR_Byte(0x00,OLED_CMD);    //设置低列地址
  •     OLED_WR_Byte(0x10,OLED_CMD);    //设置高列地址
  •     OLED_WR_Byte(0x40,OLED_CMD);    //设置起始行地址
  •     OLED_WR_Byte(0xB0,OLED_CMD);    //设置页地址
  •     OLED_WR_Byte(0x81,OLED_CMD);    // 对比度设置,可设置亮度
  •     OLED_WR_Byte(0xFF,OLED_CMD);    //  265
  •     OLED_WR_Byte(0xA1,OLED_CMD);    //设置段(SEG)的起始映射地址;column的127地址是SEG0的地址
  •     OLED_WR_Byte(0xA6,OLED_CMD);    //正常显示;0xa7逆显示
  •     OLED_WR_Byte(0xA8,OLED_CMD);    //设置驱动路数(16~64)
  •     OLED_WR_Byte(0x3F,OLED_CMD);    //64duty
  •     OLED_WR_Byte(0xC8,OLED_CMD);    //重映射模式,COM[N-1]~COM0扫描
  •     OLED_WR_Byte(0xD3,OLED_CMD);    //设置显示偏移
  •     OLED_WR_Byte(0x00,OLED_CMD);    //无偏移
  •     OLED_WR_Byte(0xD5,OLED_CMD);    //设置震荡器分频
  •     OLED_WR_Byte(0x80,OLED_CMD);    //使用默认值
  •     OLED_WR_Byte(0xD9,OLED_CMD);    //设置 Pre-Charge Period
  •     OLED_WR_Byte(0xF1,OLED_CMD);    //使用官方推荐值
  •     OLED_WR_Byte(0xDA,OLED_CMD);    //设置 com pin configuartion
  •     OLED_WR_Byte(0x12,OLED_CMD);    //使用默认值
  •     OLED_WR_Byte(0xDB,OLED_CMD);    //设置 Vcomh,可调节亮度(默认)
  •     OLED_WR_Byte(0x40,OLED_CMD);    ////使用官方推荐值
  •     OLED_WR_Byte(0x8D,OLED_CMD);    //设置OLED电荷泵
  •     OLED_WR_Byte(0x14,OLED_CMD);    //开显示
  •     OLED_WR_Byte(0xAF,OLED_CMD);    //开启OLED面板显示
  •     OLED_Clear();        //清屏
  •     OLED_Set_Pos(0,0);   //设置数据写入的起始行、列
  • }
  • /*
  • * @brief           OLED滚屏函数,范围0~1页,水平向左
  • * @param           无
  • * @retval      无
  • */
  • void OLED_Scroll(void)
  • {
  •     OLED_WR_Byte(0x2E,OLED_CMD);    //关闭滚动
  •     OLED_WR_Byte(0x27,OLED_CMD);    //水平向左滚动
  •     OLED_WR_Byte(0x00,OLED_CMD);    //虚拟字节
  •     OLED_WR_Byte(0x00,OLED_CMD);    //起始页 0
  •     OLED_WR_Byte(0x00,OLED_CMD);    //滚动时间间隔
  •     OLED_WR_Byte(0x01,OLED_CMD);    //终止页 1
  •     OLED_WR_Byte(0x00,OLED_CMD);    //虚拟字节
  •     OLED_WR_Byte(0xFF,OLED_CMD);    //虚拟字节
  •     OLED_WR_Byte(0x2F,OLED_CMD);    //开启滚动
  • }
  • 复制代码