[N32G430] 【N32G430开发板体验】软件IIC驱动OLED

[复制链接]
 楼主| shendu0032 发表于 2024-4-25 14:34 | 显示全部楼层 |阅读模式
<
本帖最后由 shendu0032 于 2024-4-25 14:35 编辑

上一篇介绍这款开发板的资料和流水灯实验,这次在上次代码的基础上添加OLED的驱动程序,软件IIC是通过GPIO引脚,软件模拟寄存器的方式来控制管脚的状态,从而模拟IIC通讯的波形,最终达到一个IIC通讯的过程。下面详细介绍IIC软件模拟通讯的4个过程,分别是1、起始信号与停止信号;2、应答信号;3、数据的有效性;4、数据传输。
1、起始信号与停止信号
起始信号:当SCL为高电平期间,SDA由高到低的跳变,起始信号是一种电平跳变的时序信号而不是一个电平信号。
停止信号:当SCL为高电平期间,SDA由低到高的跳变,停止信号也是一种电平跳变的时序信号而不是一个电平信号。起始信号和停止信号一般由主机产生。 IIC.png
  1. //IIC Start
  2. **********************************************/
  3. void OLED_IIC_Start()
  4. {

  5.         OLED_SCLK_Set();
  6.         SysTick_Delay_Us(3);
  7.         OLED_SDIN_Set();
  8.         SysTick_Delay_Us(3);
  9.         OLED_SDIN_Clr();
  10.         SysTick_Delay_Us(3);
  11.         OLED_SCLK_Clr();
  12.         SysTick_Delay_Us(3);
  13. }

  14. /**********************************************
  15. //IIC Stop
  16. **********************************************/
  17. void OLED_IIC_Stop()
  18. {
  19.         OLED_SCLK_Set();
  20.         SysTick_Delay_Us(3);
  21.         OLED_SDIN_Clr();
  22.         SysTick_Delay_Us(3);
  23.         OLED_SDIN_Set();
  24.         SysTick_Delay_Us(3);
  25.         
  26. }

为了更加直观方便的编写代码,在oled.h文件中添加宏定义,下面是oled.h文件的代码,可以看到SCL和SDA引脚分别是PA4和PA5
  1. #ifndef __OLED_H
  2. #define __OLED_H        

  3. #include "n32g430.h"
  4. #include "stdlib.h"        
  5. #include "n32g430_gpio.h"

  6. #define OLED_MODE 0
  7. #define SIZE 8
  8. #define XLevelL                0x00
  9. #define XLevelH                0x10
  10. #define Max_Column        128
  11. #define Max_Row                64
  12. #define        Brightness        0xFF
  13. #define X_WIDTH         128
  14. #define Y_WIDTH         64         

  15. #define OLED_SCLK_Clr() GPIO_Pins_Reset(GPIOA,GPIO_PIN_4)//SCL
  16. #define OLED_SCLK_Set() GPIO_Pins_Set(GPIOA,GPIO_PIN_4)

  17. #define OLED_SDIN_Clr() GPIO_Pins_Reset(GPIOA,GPIO_PIN_5)//SDA
  18. #define OLED_SDIN_Set() GPIO_Pins_Set(GPIOA,GPIO_PIN_5)

  19. //#define OLED_SCLK_Clr() (GPIOA->PBC  = GPIO_PIN_4)//SCL
  20. //#define OLED_SCLK_Set() (GPIOA->PBSC = GPIO_PIN_4)

  21. //#define OLED_SDIN_Clr() (GPIOA->PBC  = GPIO_PIN_5)//SDA
  22. //#define OLED_SDIN_Set() (GPIOA->PBSC = GPIO_PIN_5)

  23. #define OLED_CMD  0        //写命令
  24. #define OLED_DATA 1        //写数据

  25. //OLED控制用函数
  26. void OLED_WR_Byte(unsigned dat,unsigned cmd);  
  27. void OLED_Display_On(void);
  28. void OLED_Display_Off(void);                                                                                          
  29. void OLED_Init(void);
  30. void OLED_Clear(void);
  31. void OLED_DrawPoint(uint8_t x,uint8_t y,uint8_t t);
  32. void OLED_Fill(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint8_t dot);
  33. void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size);
  34. void OLED_ShowNumber(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size);
  35. void OLED_ShowString(uint8_t x,uint8_t y, uint8_t *p,uint8_t Char_Size);         
  36. void OLED_Set_Pos(unsigned char x, unsigned char y);
  37. void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no);
  38. void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[]);
  39. void fill_picture(unsigned char fill_Data);
  40. void Picture(void);
  41. void OLED_IIC_Start(void);
  42. void OLED_IIC_Stop(void);
  43. void OLED_Write_IIC_Command(unsigned char IIC_Command);
  44. void OLED_Write_IIC_Data(unsigned char IIC_Data);
  45. void OLED_Write_IIC_Byte(unsigned char IIC_Byte);
  46. void OLED_IIC_Wait_Ack(void);

  47. void OLED_fuhao_write(unsigned char x,unsigned char y,unsigned char asc);
  48. void OLED_Num_write(unsigned char x,unsigned char y,unsigned char asc) ;
  49. void OLED_Float(unsigned char Y,unsigned char X,double real,unsigned char N);
  50. void OLED_Float2(unsigned char Y,unsigned char X,double real,unsigned char N1,unsigned char N2);
  51. void OLED_Num2(unsigned char x,unsigned char y, int number);
  52. void OLED_Num3(unsigned char x,unsigned char y,int number);
  53. void OLED_Num4(unsigned char x,unsigned char y, int number);
  54. void OLED_Num5(unsigned char x,unsigned char y,unsigned int number);

  55. void OLED_GPIO_Configuare(void);
  56. #endif  

2、从机应答信号
主机每发送一个字节吗,就在时钟脉冲9期间释放数据线,由从机反馈一个应答信号。应答信号为低电平时规定为有效应答位(ACK简称应答位)表示从机已经成功接收到该字节。应答信号为高电平时,规定为非应答位,一般表示从机接收该字节没有成功。对于反馈有效应答位ACK的要求是从机在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。在图中红色可以看到,SCL为低电平后SDA再升为高电平,再SCL变为高电平,由此可以进行一个软件模拟IIC波形。
应答信号.png
  1. void OLED_IIC_Wait_Ack()
  2. {
  3.         OLED_SCLK_Set();
  4.         SysTick_Delay_Us(3);
  5.         OLED_SCLK_Clr();
  6.         SysTick_Delay_Us(3);
  7. }

3、数据有效性
IIC总线进行数据传输时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。SDA数据线在SCL的每个时钟周期传输一位数据。即数据在SCL的上升沿到来之前就需要准备好,并在下降沿到来之前必须稳定。
4、数据传输
在数据有效性中,数据位的传输是边沿触发的,在IIC总线上数据传输,传送的每一位数据都有一个时钟脉冲相对应,SCL为高电平时SDA表示数据有效,即此时的SDA为高电平时表示数据“1”,为低电平时表示数据“0”.即在SCL串行时钟的配合下,SDA上逐位地串行传送每一位数据。传输数据地时候,将SCL置低,然后设置SDA总线对应地引脚电平为高/低,SDA电平确定后再将SCL置高,将8位由高到低依次发送出去。
  1. // IIC Write byte
  2. **********************************************/
  3. void OLED_Write_IIC_Byte(unsigned char IIC_Byte)
  4. {
  5.         unsigned char i;
  6.         unsigned char m,da;
  7.         da=IIC_Byte;
  8.         OLED_SCLK_Clr();
  9.         for(i=0;i<8;i++)               
  10.         {
  11.                 m=da;
  12.                 //        OLED_SCLK_Clr();
  13.                 m=m&0x80;
  14.                 if(m==0x80)
  15.                 {
  16.                         OLED_SDIN_Set();
  17.                 }
  18.                 else
  19.                         OLED_SDIN_Clr();
  20.                 da=da<<1;
  21.                 SysTick_Delay_Us(3);
  22.                 OLED_SCLK_Set();
  23.                 SysTick_Delay_Us(3);
  24.                 OLED_SCLK_Clr();
  25.                 SysTick_Delay_Us(3);
  26.         }
  27. }
  28. /**********************************************
  29. // IIC Write Command
  30. **********************************************/
  31. void OLED_Write_IIC_Command(unsigned char IIC_Command)
  32. {
  33.                 OLED_IIC_Start();
  34.                 OLED_Write_IIC_Byte(0x78);            //Slave address,SA0=0
  35.                 OLED_IIC_Wait_Ack();        
  36.                 OLED_Write_IIC_Byte(0x00);                        //write command
  37.                 OLED_IIC_Wait_Ack();        
  38.                 OLED_Write_IIC_Byte(IIC_Command);
  39.                 OLED_IIC_Wait_Ack();        
  40.                 OLED_IIC_Stop();
  41. }
  42. /**********************************************
  43. // IIC Write Data
  44. **********************************************/
  45. void OLED_Write_IIC_Data(unsigned char IIC_Data)
  46. {
  47.                 OLED_IIC_Start();
  48.                 OLED_Write_IIC_Byte(0x78);                        //D/C#=0; R/W#=0
  49.                 OLED_IIC_Wait_Ack();        
  50.                 OLED_Write_IIC_Byte(0x40);                        //write data
  51.                 OLED_IIC_Wait_Ack();        
  52.                 OLED_Write_IIC_Byte(IIC_Data);
  53.                 OLED_IIC_Wait_Ack();        
  54.                 OLED_IIC_Stop();
  55. }
  56. void OLED_WR_Byte(unsigned dat,unsigned cmd)
  57. {
  58.         if(cmd)
  59.         {
  60.    OLED_Write_IIC_Data(dat);
  61.         }
  62.         else
  63.         {
  64.    OLED_Write_IIC_Command(dat);
  65.         }
  66. }

本次实验用的是OLED模块(0.96寸4针IIC接口OLED显示屏)SSD1306,电源电压3.3-5.5V,总共四个接口,GNDVCC,SCL(IIC总线时钟信号),SDA(IIC总线数据信号)SSD1306是一个为映射静态 RAM 保存位模式来显示。该 RAM 的为 128 * 64 bit大小,RAM 分为 8 页,从 PAFE0 到 PAGE7,用于单色 128 * 64 点阵显示。下面是OLED引脚初始化和OLED初始化程序

  1. void OLED_GPIO_Configuare(void)
  2. {
  3.     GPIO_InitType GPIO_InitStructure;
  4.           RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);
  5.     GPIO_Structure_Initialize(&GPIO_InitStructure);      
  6.         /* Select the GPIO pin to control */
  7.     GPIO_InitStructure.Pin          = GPIO_PIN_4|GPIO_PIN_5;
  8.         /* Set pin mode to general push-pull output */
  9.     GPIO_InitStructure.GPIO_Mode    = GPIO_MODE_OUT_PP;
  10.                 GPIO_InitStructure.GPIO_Pull      = GPIO_PULL_UP;
  11.         /* Set the pin drive current to 4MA*/
  12.     GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
  13.         /* Initialize GPIO */
  14.     GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);
  15.                 GPIO_Pins_Set(GPIOA,GPIO_PIN_4|GPIO_PIN_5);
  16. }

  17. //初始化SSD1306                                            
  18. void OLED_Init(void)
  19. {

  20.         OLED_GPIO_Configuare();
  21.         SysTick_Delay_Ms(200);
  22.         OLED_WR_Byte(0xAE,OLED_CMD);//--display off
  23.         OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
  24.         OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
  25.         OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  
  26.         OLED_WR_Byte(0xB0,OLED_CMD);//--set page address
  27.         OLED_WR_Byte(0x81,OLED_CMD); // contract control
  28.         OLED_WR_Byte(0xFF,OLED_CMD);//--128   
  29.         OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap
  30.         OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
  31.         OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
  32.         OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
  33.         OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
  34.         OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
  35.         OLED_WR_Byte(0x00,OLED_CMD);//
  36.         
  37.         OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
  38.         OLED_WR_Byte(0x80,OLED_CMD);//
  39.         
  40.         OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
  41.         OLED_WR_Byte(0x05,OLED_CMD);//
  42.         
  43.         OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
  44.         OLED_WR_Byte(0xF1,OLED_CMD);//
  45.         
  46.         OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
  47.         OLED_WR_Byte(0x12,OLED_CMD);//
  48.         
  49.         OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
  50.         OLED_WR_Byte(0x30,OLED_CMD);//
  51.         
  52.         OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
  53.         OLED_WR_Byte(0x14,OLED_CMD);//
  54.         
  55.         OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
  56.         OLED_Clear();
  57.         OLED_Set_Pos(0,0);
  58.         
  59. }  
写入起始坐标
  1. //坐标设置
  2. void OLED_Set_Pos(unsigned char x, unsigned char y)
  3. {         
  4.         OLED_WR_Byte(0xb0+y,OLED_CMD);
  5.         OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
  6.         OLED_WR_Byte((x&0x0f),OLED_CMD);
  7. }
清屏函数
  1. //清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!         
  2. void OLED_Clear(void)  
  3. {  
  4.         uint8_t i,n;                    
  5.         for(i=0;i<8;i++)  
  6.         {  
  7.                 OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
  8.                 OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
  9.                 OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
  10.                 for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);
  11.         } //更新显示
  12. }
开启&关闭OLED显示
  1. //开启OLED显示   
  2. void OLED_Display_On(void)
  3. {
  4.         OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
  5.         OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
  6.         OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
  7. }
  8. //关闭OLED显示     
  9. void OLED_Display_Off(void)
  10. {
  11.         OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
  12.         OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
  13.         OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
  14. }               
显示字符,数字,字符串,汉字等函数代码
  1. //在指定位置显示一个字符,包括部分字符
  2. //x:0~127
  3. //y:0~63
  4. //mode:0,反白显示;1,正常显示                                 
  5. //size:选择字体 16/12
  6. void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size)
  7. {              
  8.         unsigned char c=0,i=0;        
  9.                 c=chr-' ';//得到偏移后的值                        
  10.                 if(x>Max_Column-1){x=0;y=y+2;}
  11.                 if(Char_Size ==16)
  12.                         {
  13.                         OLED_Set_Pos(x,y);        
  14.                         for(i=0;i<8;i++)
  15.                         OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
  16.                         OLED_Set_Pos(x,y+1);
  17.                         for(i=0;i<8;i++)
  18.                         OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
  19.                         }
  20.                         else {        
  21.                                 OLED_Set_Pos(x,y);
  22.                                 for(i=0;i<6;i++)
  23.                                 OLED_WR_Byte(F6x8[c][i],OLED_DATA);
  24.                                 
  25.                         }
  26. }
  27. //m^n函数
  28. uint32_t oled_pow(uint8_t m,uint8_t n)
  29. {
  30.         uint32_t result=1;         
  31.         while(n--)result*=m;   
  32.         return result;
  33. }                                 
  34. //显示2个数字
  35. //x,y :起点坐标         
  36. //len :数字的位数
  37. //size:字体大小
  38. //mode:模式        0,填充模式;1,叠加模式
  39. //num:数值(0~4294967295);                           
  40. void OLED_ShowNumber(uint8_t x,uint8_t y,uint32_t        num,uint8_t len,uint8_t size2)
  41. {                 
  42.         uint8_t t,temp;
  43.         uint8_t enshow=0;                                                   
  44.         for(t=0;t<len;t++)
  45.         {
  46.                 temp=(num/oled_pow(10,len-t-1))%10;
  47.                 if(enshow==0&&t<(len-1))
  48.                 {
  49.                         if(temp==0)
  50.                         {
  51.                                 OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
  52.                                 continue;
  53.                         }else enshow=1;
  54.                           
  55.                 }
  56.                  OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
  57.         }
  58. }
  59. //显示一个字符号串
  60. void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t Char_Size)
  61. {
  62.         while (*chr!='\0')
  63.         {                OLED_ShowChar(x,y,*chr,Char_Size);
  64.                         x+=8;
  65.                 if(x>120){x=0;y+=2;}
  66.                         chr++;
  67.         }
  68. }
  69. //显示汉字
  70. void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no)
  71. {                                 
  72.         uint8_t t,adder=0;
  73.         OLED_Set_Pos(x,y);        
  74.     for(t=0;t<16;t++)
  75.                 {
  76.                                 OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
  77.                                 adder+=1;
  78.      }        
  79.                 OLED_Set_Pos(x,y+1);        
  80.     for(t=0;t<16;t++)
  81.                         {        
  82.                                 OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
  83.                                 adder+=1;
  84.       }                                       
  85. }
  86. /***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
  87. void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[])
  88. {         
  89. unsigned int j=0;
  90. unsigned char x,y;
  91.   
  92.   if(y1%8==0) y=y1/8;      
  93.   else y=y1/8+1;
  94.         for(y=y0;y<y1;y++)
  95.         {
  96.                 OLED_Set_Pos(x0,y);
  97.     for(x=x0;x<x1;x++)
  98.             {      
  99.                     OLED_WR_Byte(BMP[j++],OLED_DATA);                    
  100.             }
  101.         }
  102. }
  103. void OLED_Float(unsigned char Y,unsigned char X,double real,unsigned char N)
  104. {
  105.    unsigned char   i_Count=1;
  106.    unsigned char   n[12]={0};
  107.    long   j=1;  
  108.    int    real_int=0;
  109.    double decimal=0;
  110.    unsigned int   real_decimal=0;
  111.    if(real<0)
  112.          {
  113.                  real_int=(int)(-real);
  114.          }
  115.          else
  116.          {
  117.                  real_int=(int)real;
  118.    }
  119.          decimal=real-real_int;
  120.    real_decimal=decimal*1e4;
  121.    while(real_int/10/j!=0)
  122.    {
  123.       j=j*10;i_Count++;  
  124.    }
  125.    n[0]=(real_int/10000)%10;
  126.    n[1]=(real_int/1000)%10;
  127.    n[2]=(real_int/100)%10;
  128.    n[3]=(real_int/10)%10;
  129.    n[4]=(real_int/1)%10;
  130.    n[5]='.';
  131.    n[6]=(real_decimal/1000)%10;
  132.    n[7]=(real_decimal/100)%10;
  133.    n[8]=(real_decimal/10)%10;
  134.    n[9]=real_decimal%10;
  135.    n[6+N]='\0';
  136.    for(j=0;j<10;j++) n[j]=n[j]+16+32;
  137.          if(real<0)
  138.          {                 
  139.                  i_Count+=1;
  140.                  n[5-i_Count]='-';
  141.          }
  142.    n[5]='.';
  143.    n[6+N]='\0';   
  144.    OLED_ShowString(X,Y,&n[5-i_Count],12);
  145. }

  146. void OLED_Float2(unsigned char Y,unsigned char X,double real,unsigned char N1,unsigned char N2)
  147. {
  148.    unsigned char   i_Count=1;
  149.    unsigned char   n[12]={0};
  150.    long   j=1;  
  151.    unsigned int   real_int=0;
  152.    double decimal=0;
  153.    unsigned int   real_decimal=0;
  154.    X=X*8;
  155.    real_int=(int)real;
  156.    //Dis_Num(2,0,real_int,5);
  157.    decimal=real-real_int;
  158.    real_decimal=decimal*1e4;
  159.    //Dis_Num(2,6,real_decimal,4);
  160.    while(real_int/10/j!=0)
  161.    {
  162.       j=j*10;i_Count++;  
  163.    }
  164.    n[0]=(real_int/10000)%10;
  165.    n[1]=(real_int/1000)%10;
  166.    n[2]=(real_int/100)%10;
  167.    n[3]=(real_int/10)%10;

  168.    n[5]='.';
  169.    n[6]=(real_decimal/1000)%10;
  170.    n[7]=(real_decimal/100)%10;
  171.    n[8]=(real_decimal/10)%10;
  172.    n[9]=real_decimal%10;
  173.    n[6+N2]='\0';
  174.    for(j=0;j<10;j++) n[j]=n[j]+16+32;
  175.    n[5]='.';
  176.    n[6+N2]='\0';   
  177.    OLED_ShowString(X,Y,&n[5-N1],12);
  178. }

  179. void OLED_Num2(unsigned char x,unsigned char y, int number)
  180. {
  181.         unsigned char shi,ge;
  182.               int num =number;
  183.         if(num<0)
  184.         {
  185.                 num=-num;
  186.                 shi=num%100/10;
  187.     ge=num%10;
  188.           OLED_fuhao_write(x,y,13);
  189.     OLED_Num_write(x+1,y,shi);
  190.     OLED_Num_write(x+2,y,ge);
  191.   }
  192.   else
  193.         {

  194.                 shi=num%100/10;
  195.     ge=num%10;
  196.                 OLED_fuhao_write(x,y,11);
  197.     OLED_Num_write(x+1,y,shi);
  198.     OLED_Num_write(x+2,y,ge);
  199.   }
  200.         
  201. }

  202. void OLED_Num3(unsigned char x,unsigned char y,int number)
  203. {
  204.   unsigned char ge,shi,bai;
  205.         int num =number;
  206.         if(num<0)
  207.         {
  208.                     num=-num;
  209.                     OLED_fuhao_write(x,y,13); //显示-号
  210.         ge = num %10;
  211.         shi = num/10%10;
  212.         bai = num/100;
  213.         OLED_Num_write(x+3,y,ge);
  214.         OLED_Num_write(x+2,y,shi);
  215.         OLED_Num_write(x+1,y,bai);
  216.         }
  217.         else
  218.         {
  219.        OLED_fuhao_write(x,y,11);
  220.         ge = num %10;
  221.         shi = num/10 %10;
  222.         bai = num/100;
  223.         OLED_Num_write(x+3,y,ge);
  224.         OLED_Num_write(x+2,y,shi);
  225.         OLED_Num_write(x+1,y,bai);
  226.   }
  227. }

  228. void OLED_Num4(unsigned char x,unsigned char y, int number)
  229. {
  230.         unsigned char qian,bai,shi,ge;
  231.         int num =number;
  232.         if(num<0)
  233.         {
  234.                 num=-num;
  235.         }
  236.         qian=num/1000;
  237.         bai=num%1000/100;
  238.         shi=num%100/10;
  239.         ge=num%10;

  240.         OLED_Num_write(x,y,qian);
  241.         OLED_Num_write(x+1,y,bai);
  242.         OLED_Num_write(x+2,y,shi);
  243.         OLED_Num_write(x+3,y,ge);
  244. }

  245. void OLED_Num_write(unsigned char x,unsigned char y,unsigned char asc)
  246. {
  247.         int i=0;
  248.         OLED_Set_Pos(x*6,y);
  249.         for(i=0;i<6;i++)
  250.         {
  251.                  OLED_WR_Byte(F6x8[asc+16][i],OLED_DATA);         
  252.         }
  253. }        
  254. void OLED_fuhao_write(unsigned char x,unsigned char y,unsigned char asc)
  255. {

  256.           int i=0;
  257.     OLED_Set_Pos(x*6,y);
  258.     for(i=0;i<6;i++)
  259.     {
  260.        OLED_WR_Byte(F6x8[asc][i],OLED_DATA);         
  261.     }

  262. }                        

  263. void OLED_Num5(unsigned char x,unsigned char y,unsigned int number)
  264. {
  265.         unsigned char wan,qian,bai,shi,ge;
  266.         wan=number/10000;
  267.                     qian = number%10000/1000;
  268.         bai=number%1000/100;
  269.         shi=number%100/10;
  270.         ge=number%10;
  271.         OLED_Num_write(x,y,wan);
  272.         OLED_Num_write(x+1,y,qian);
  273.         OLED_Num_write(x+2,y,bai);
  274.         OLED_Num_write(x+3,y,shi);
  275.                     OLED_Num_write(x+4,y,ge);
  276. }
这里面要使用取模软件01-PCtoLCD2002完美版,可以实现汉字、图片、英文的取模。首先双击打开软件
取模软件.png
点击模式,选择字符模式
字模选项.png
点击选项按钮,进行配置,点阵内的数字手动输入999,所有设置完成后点击确定
选项设置.png
以生成16*16的汉字为例,字宽和字高选择16,在输入栏输入需要取模的汉字,且只能是汉字,然后点击生成字模按钮
生成代码.png
将生成的代码复制到oledfont.h文件的数组中
  1. char Hzk[][32]={

  2. {0x00,0xFE,0x02,0x12,0x92,0x92,0x92,0xF2,0x92,0x92,0x92,0x12,0x02,0xFE,0x00,0x00},
  3. {0x00,0xFF,0x40,0x48,0x48,0x48,0x48,0x4F,0x48,0x4A,0x4C,0x48,0x40,0xFF,0x00,0x00},/*"国",0*/

  4. {0x00,0x00,0xFE,0x22,0x22,0x22,0x22,0x22,0xE2,0x22,0x22,0x22,0x3E,0x00,0x00,0x00},
  5. {0x00,0x00,0xFF,0x41,0x21,0x11,0x01,0x01,0x03,0x0D,0x11,0x21,0x41,0xF1,0x00,0x00},/*"民",1*/

  6. {0x10,0x10,0x10,0xFF,0x10,0x90,0x08,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x08,0x00},
  7. {0x04,0x44,0x82,0x7F,0x01,0x80,0x80,0x40,0x43,0x2C,0x10,0x28,0x46,0x81,0x80,0x00},/*"技",2*/

  8. {0x00,0x10,0x10,0x10,0x10,0xD0,0x30,0xFF,0x30,0xD0,0x12,0x1C,0x10,0x10,0x00,0x00},
  9. {0x10,0x08,0x04,0x02,0x01,0x00,0x00,0xFF,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x00},/*"术",3*/

  10. {0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x00},
  11. {0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00},/*"二",4*/

  12. {0x10,0xF0,0x1F,0x10,0xF0,0x04,0xD4,0x54,0x54,0xFF,0x54,0x54,0x74,0x04,0x00,0x00},
  13. {0x41,0x22,0x14,0x0C,0x33,0x80,0x41,0x21,0x19,0x07,0x19,0x25,0x49,0x87,0x80,0x00},/*"姨",5*/

  14. {0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0xF8,0x00,0x00,0x00},
  15. {0x00,0x00,0x1F,0x08,0x08,0x08,0x08,0x7F,0x88,0x88,0x88,0x88,0x9F,0x80,0xF0,0x00},/*"电",6*/

  16. {0x80,0x82,0x82,0x82,0x82,0x82,0x82,0xE2,0xA2,0x92,0x8A,0x86,0x82,0x80,0x80,0x00},
  17. {0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"子",7*/

  18. {0x00,0xFE,0x02,0x22,0x42,0x82,0x72,0x02,0x22,0x42,0x82,0x72,0x02,0xFE,0x00,0x00},
  19. {0x00,0xFF,0x10,0x08,0x06,0x01,0x0E,0x10,0x08,0x06,0x01,0x4E,0x80,0x7F,0x00,0x00},/*"网",8*/

  20. {0x10,0x60,0x02,0x8C,0x00,0xFE,0x02,0xF2,0x02,0xFE,0x00,0xF8,0x00,0xFF,0x00,0x00},
  21. {0x04,0x04,0x7E,0x01,0x80,0x47,0x30,0x0F,0x10,0x27,0x00,0x47,0x80,0x7F,0x00,0x00},/*"测",9*/

  22. {0x40,0x40,0x42,0xCC,0x00,0x90,0x90,0x90,0x90,0x90,0xFF,0x10,0x11,0x16,0x10,0x00},
  23. {0x00,0x00,0x00,0x3F,0x10,0x28,0x60,0x3F,0x10,0x10,0x01,0x0E,0x30,0x40,0xF0,0x00},/*"试",10*/

  24. };
完成上述过程之后,在main函数添加必要的头文件和初始化代码,可以在while循环中执行以下显示代码
  1.   OLED_ShowCHinese(15,2,0);
  2.                 OLED_ShowCHinese(42,2,1);               
  3.                 OLED_ShowCHinese(70,2,2);               
  4.                 OLED_ShowCHinese(98,2,3);               
  5.                 OLED_ShowCHinese(23,0,4);
  6.                 OLED_ShowCHinese(39,0,5);               
  7.                 OLED_ShowCHinese(55,0,6);               
  8.                 OLED_ShowCHinese(71,0,7);       
  9.                 OLED_ShowCHinese(87,0,8);       
  10.                 OLED_ShowString(23,4,"N32G430CBL7",16);       
  11.                 OLED_ShowString(31,6,"OLED",16);               
  12.                 OLED_ShowCHinese(64,6,9);       
  13.                 OLED_ShowCHinese(80,6,10);       

效果.jpg

评论

同款取模软件,不过这种字库基本上就是固定的了,没法缩放  发表于 2024-4-25 17:16
慢醇 发表于 2024-8-31 18:22 | 显示全部楼层
如果是ACK信号,SDA会被拉低;如果是NACK信号,SDA会保持高电平。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:总是缺乏自信,进进退退,走走停停,不停的自我耗损,又不断的为自我耗损而再耗损。

33

主题

261

帖子

7

粉丝
快速回复 在线客服 返回列表 返回顶部