[PIC®/AVR®/dsPIC®产品] 使用pic18f47q10驱动 ssd1306的OLED

[复制链接]
 楼主| 幸福小强 发表于 2025-5-29 16:00 | 显示全部楼层 |阅读模式
用于在 PIC18F47Q10 微控制器上使用 I2C 连接 0.91 英寸 SSD1306 OLED 显示屏。
该示例初始化显示并演示基本的绘图功能,包括简单的像素动画。


  1. /*
  2. * File:   main.c
  3. * Author: maxymsmal
  4. *
  5. * Created on April 9, 2025, 11:25 PM
  6. */

  7. // Config bytes
  8. #pragma config WDTE = OFF
  9. #pragma config LVP = ON

  10. #include <pic18.h>
  11. #include <xc.h>
  12. #include "i2c_hw.h"
  13. #include "ssd1306_display.h"

  14. #define _XTAL_FREQ 32000000UL

  15. void hw_init(void);

  16. void main(void)
  17. {
  18.   hw_init();

  19.   __delay_ms(100);

  20.   LATEbits.LATE0 = 0;

  21.   ssd1306_InitDisplay();

  22.   LATEbits.LATE0 = 1;

  23.   __delay_ms(100);

  24.   while (1) {
  25.     ssd1306_DemoAnimation();
  26.     __delay_ms(1000);
  27.   }
  28. }

  29. void hw_init(void)
  30. {
  31.   OSCCON1bits.NOSC = 0x6;
  32.   OSCFRQbits.FRQ3 = 0x08;
  33. // OSCFRQ = 0x08;


  34.   ANSELBbits.ANSELB1 = 0;
  35.   ANSELBbits.ANSELB2 = 0;

  36.   TRISBbits.TRISB5 = 0;
  37.   TRISBbits.TRISB4 = 0;

  38.   TRISEbits.TRISE0 = 0;
  39.   TRISEbits.TRISE1 = 0;

  40.   LATEbits.LATE1 = 1;
  41.   LATEbits.LATE0 = 0;

  42.   WPUBbits.WPUB1 = 1;
  43.   WPUBbits.WPUB2 = 1;

  44.   SSP1CL**S = 0x09;
  45.   RB1PPS = 0x0F;

  46.   SSP1DATPPS = 0x0A;
  47.   RB2PPS = 0x10;
  48.   
  49.   SSP1CON1bits.SSPM3 = 1; /// Clock = F_OSC / (4 * (SSP1ADD + 1))
  50.   LATEbits.LATE0 = 1;

  51.   SSP1ADD = 0x13;//0x9F;   // Set the boud rate devider
  52. }


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
玛尼玛尼哄 发表于 2025-5-29 16:02 | 显示全部楼层
不错,下载附件,希望这个OLED的库能有用。
小灵通2018 发表于 2025-5-29 16:32 | 显示全部楼层
这是用IO模拟的还是用硬件的I2C?
小灵通2018 发表于 2025-5-29 16:33 | 显示全部楼层
好像是硬件的,看到配置相关的寄存器了。
小灵通2018 发表于 2025-5-29 16:35 | 显示全部楼层

  1. #include <stdint.h>
  2. #include <stddef.h>
  3. #include <string.h>

  4. #include "ssd1306_display.h"
  5. #include "i2c_hw.h"
  6. #include "ssd1306_font.h"

  7. uint8_t buffer[SSD1306_WIDTH * (SSD1306_HEIGHT / 8)];

  8. void ssd1306_InitDisplay(void)
  9. {
  10.   ssd1306_WriteCommand(0xAE);
  11.   ssd1306_WriteCommand(0xD5);
  12.   ssd1306_WriteCommand(0x80);
  13.   ssd1306_WriteCommand(0xA8);
  14.   ssd1306_WriteCommand(0x1F);
  15.   ssd1306_WriteCommand(0xD3);
  16.   ssd1306_WriteCommand(0x00);
  17.   ssd1306_WriteCommand(0x40);
  18.   ssd1306_WriteCommand(0x8D);
  19.   ssd1306_WriteCommand(0x14);
  20.   ssd1306_WriteCommand(0x20);
  21.   ssd1306_WriteCommand(0x00);
  22.   ssd1306_WriteCommand(0xA1);
  23.   ssd1306_WriteCommand(0xC8);
  24.   ssd1306_WriteCommand(0xDA);
  25.   ssd1306_WriteCommand(0x02);
  26.   ssd1306_WriteCommand(0x81);
  27.   ssd1306_WriteCommand(0x8F);
  28.   ssd1306_WriteCommand(0xD9);
  29.   ssd1306_WriteCommand(0xF1);
  30.   ssd1306_WriteCommand(0xDB);
  31.   ssd1306_WriteCommand(0x40);
  32.   ssd1306_WriteCommand(0xA4);
  33.   ssd1306_WriteCommand(0xA6);
  34.   ssd1306_WriteCommand(0x2E);
  35.   ssd1306_WriteCommand(0xAF);

  36.   ssd1306_ClearDisplay();
  37.   ssd1306_SetDisplay();
  38. }

  39. void ssd1306_WriteCommand(uint8_t command)
  40. {
  41.   I2C1_open();
  42.   I2C1_startCondition();

  43.   I2C1_sendData((SSD1306_I2C_ADDR << 1) & ~0x01);
  44.   if (I2C1_getAckstatBit())
  45.   {
  46.     I2C1_stopCondition();
  47.     I2C1_close();
  48.   }

  49.   I2C1_sendData(0x00);
  50.   if (I2C1_getAckstatBit())
  51.   {
  52.     I2C1_stopCondition();
  53.     I2C1_close();
  54.   }

  55.   I2C1_sendData(command);
  56. }

  57. void ssd1306_WriteData(uint8_t *data, size_t size)
  58. {
  59.   I2C1_open();
  60.   I2C1_startCondition();

  61.   I2C1_sendData((SSD1306_I2C_ADDR << 1) & ~0x01);

  62.   if (I2C1_getAckstatBit()){
  63.     I2C1_stopCondition();
  64.     I2C1_close();
  65.   }

  66.   I2C1_sendData(0x40);
  67.   if (I2C1_getAckstatBit()) {
  68.     I2C1_stopCondition();
  69.     I2C1_close();
  70.   }

  71.   for (size_t i = 0; i < size; i++) {
  72.     I2C1_sendData(data[i]);

  73.     if (I2C1_getAckstatBit()) {
  74.       break;
  75.     }
  76.   }
  77. }

  78. void ssd1306_SetDisplay(void)
  79. {
  80.   for (uint8_t page = 0; page < (SSD1306_HEIGHT / 8); page++)
  81.   {
  82.     ssd1306_WriteCommand(0xB0 + page);
  83.     ssd1306_WriteCommand(0x00);
  84.     ssd1306_WriteCommand(0x10);

  85.     ssd1306_WriteData(&buffer[SSD1306_WIDTH * page], SSD1306_WIDTH);
  86.   }
  87. }

  88. void ssd1306_SetDisplay_Horisontal(void)
  89. {
  90.   ssd1306_WriteCommand(0x20);                 // Memory Addressing Mode
  91.   ssd1306_WriteCommand(0x00);                 // Horizontal Addressing Mode

  92.   ssd1306_WriteCommand(0x21);                 // column address
  93.   ssd1306_WriteCommand(0);                    // Start column
  94.   ssd1306_WriteCommand(SSD1306_WIDTH - 1);
  95.   
  96.   ssd1306_WriteCommand(0x22); // Set page address
  97.   ssd1306_WriteCommand(0);    // Start page
  98.   ssd1306_WriteCommand((SSD1306_HEIGHT / 8) - 1); // End page

  99.   ssd1306_WriteData(buffer, SSD1306_WIDTH * (SSD1306_HEIGHT / 8));
  100. }

  101. void ssd1306_SetDisplay_Vertical(void)
  102. {
  103.   ssd1306_WriteCommand(0x20);                 // Memory Addressing Mode
  104.   ssd1306_WriteCommand(0x01);                 // Vertical Addressing Mode
  105.    
  106.   ssd1306_WriteCommand(0x21);                 // column address
  107.   ssd1306_WriteCommand(0);                    // Start column
  108.   ssd1306_WriteCommand(SSD1306_WIDTH - 1);
  109.    
  110.   ssd1306_WriteCommand(0x22); // Set page address
  111.   ssd1306_WriteCommand(0);    // Start page
  112.   ssd1306_WriteCommand((SSD1306_HEIGHT / 8) - 1); // End page

  113.   ssd1306_WriteData(buffer, SSD1306_WIDTH * (SSD1306_HEIGHT / 8));
  114. }

  115. void ssd1306_ClearDisplay(void)
  116. {
  117.   memset(buffer, 0, sizeof(buffer));
  118. }

  119. void ssd1306_EnableDisplay(uint8_t state)
  120. {
  121.   ssd1306_WriteCommand(state ? 0xAF : 0xAE);
  122. }

  123. void ssd1306_SetContrast(uint8_t value)
  124. {
  125.   ssd1306_WriteCommand(0x81);
  126.   ssd1306_WriteCommand(value);
  127. }

  128. void ssd1306_SetInversionMode(uint8_t setInversion)
  129. {
  130.   ssd1306_WriteCommand(setInversion ? 0xA7 : 0xA6);
  131. }

  132. void ssd1306_SetEntireMode(uint8_t state)
  133. {
  134.   ssd1306_WriteCommand(state ? 0xA5 : 0xA4);
  135. }

  136. void ssd1306_SetPixel(int16_t x, int16_t y, uint8_t color)
  137. {
  138.   if (x < 0 || x >= SSD1306_WIDTH || y < 0 || y >= SSD1306_HEIGHT)
  139.     return;

  140.   uint16_t byteIndex = x + (y / 8) * SSD1306_WIDTH;
  141.   uint8_t bitMask = 1 << (y % 8);

  142.   if (color)
  143.     buffer[byteIndex] |= bitMask;
  144.   else
  145.     buffer[byteIndex] &= ~bitMask;
  146. }

  147. void ssd1306_SetCursor(uint8_t x, uint8_t y) {
  148.   ssd1306_WriteCommand(0x21); // Set column address
  149.   ssd1306_WriteCommand(x);    // Start column
  150.   ssd1306_WriteCommand(127);  // End column

  151.   ssd1306_WriteCommand(0x22); // Set page address
  152.   ssd1306_WriteCommand(y);    // Start page
  153.   ssd1306_WriteCommand(0x07); // End page
  154. }

  155. void ssd1306_SetChar(char c) {
  156.   const uint8_t* charMap = _charASCIIMap[c - 32];
  157.   uint8_t charBuffer[6];
  158.   
  159.   if (c < 32 || c > 126) {
  160.       c = '?';
  161.   }
  162.   
  163.   for (int i = 0; i < 5; i++) {
  164.     charBuffer[i] = charMap[i];
  165.   }
  166.   charBuffer[5] = 0x00;

  167.   ssd1306_WriteData(charBuffer, sizeof(charBuffer));
  168. }

  169. void ssd1306_PutString(const char* str) {
  170.   while (*str) {
  171.     ssd1306_SetChar(*str++);
  172.   }
  173. }

  174. void ssd1306_DemoAnimation(void) {  
  175.   ssd1306_ClearDisplay();

  176.   for (int i = 0; i < 120; i += 5)
  177.   {
  178.     ssd1306_ClearDisplay();

  179.     for (int x = i; x < i + 30 && x < 128; x++)
  180.     {
  181.       for (int y = 5; y < 25; y++)
  182.       {
  183.         ssd1306_SetPixel(x, y, 1);
  184.       }
  185.     }
  186.       
  187.     ssd1306_SetDisplay();
  188.   }
  189.   
  190.   ssd1306_ClearDisplay();         
  191.   ssd1306_SetCursor(15, 0);
  192.   ssd1306_PutString("Hello, world!");
  193. }

小明的同学 发表于 2025-5-29 18:49 | 显示全部楼层
学习一下驱动方法
wanduzi 发表于 2025-5-29 21:55 | 显示全部楼层
这些常用的模块驱动,是必须要掌握的。
暖心小太阳 发表于 2025-6-3 08:47 | 显示全部楼层
这个示例代码看起来很不错,你已经成功地将PIC18F47Q10与SSD1306 OLED显示屏通过I2C连接起来了。动画演示部分应该能很好地展示基本的绘图功能。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

143

主题

1720

帖子

2

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