使用pic18f47q10驱动 ssd1306的OLED
用于在 PIC18F47Q10 微控制器上使用 I2C 连接 0.91 英寸 SSD1306 OLED 显示屏。该示例初始化显示并演示基本的绘图功能,包括简单的像素动画。
/*
* File: main.c
* Author: maxymsmal
*
* Created on April 9, 2025, 11:25 PM
*/
// Config bytes
#pragma config WDTE = OFF
#pragma config LVP = ON
#include <pic18.h>
#include <xc.h>
#include "i2c_hw.h"
#include "ssd1306_display.h"
#define _XTAL_FREQ 32000000UL
void hw_init(void);
void main(void)
{
hw_init();
__delay_ms(100);
LATEbits.LATE0 = 0;
ssd1306_InitDisplay();
LATEbits.LATE0 = 1;
__delay_ms(100);
while (1) {
ssd1306_DemoAnimation();
__delay_ms(1000);
}
}
void hw_init(void)
{
OSCCON1bits.NOSC = 0x6;
OSCFRQbits.FRQ3 = 0x08;
// OSCFRQ = 0x08;
ANSELBbits.ANSELB1 = 0;
ANSELBbits.ANSELB2 = 0;
TRISBbits.TRISB5 = 0;
TRISBbits.TRISB4 = 0;
TRISEbits.TRISE0 = 0;
TRISEbits.TRISE1 = 0;
LATEbits.LATE1 = 1;
LATEbits.LATE0 = 0;
WPUBbits.WPUB1 = 1;
WPUBbits.WPUB2 = 1;
SSP1CL**S = 0x09;
RB1PPS = 0x0F;
SSP1DATPPS = 0x0A;
RB2PPS = 0x10;
SSP1CON1bits.SSPM3 = 1; /// Clock = F_OSC / (4 * (SSP1ADD + 1))
LATEbits.LATE0 = 1;
SSP1ADD = 0x13;//0x9F; // Set the boud rate devider
}
不错,下载附件,希望这个OLED的库能有用。 这是用IO模拟的还是用硬件的I2C? 好像是硬件的,看到配置相关的寄存器了。
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "ssd1306_display.h"
#include "i2c_hw.h"
#include "ssd1306_font.h"
uint8_t buffer;
void ssd1306_InitDisplay(void)
{
ssd1306_WriteCommand(0xAE);
ssd1306_WriteCommand(0xD5);
ssd1306_WriteCommand(0x80);
ssd1306_WriteCommand(0xA8);
ssd1306_WriteCommand(0x1F);
ssd1306_WriteCommand(0xD3);
ssd1306_WriteCommand(0x00);
ssd1306_WriteCommand(0x40);
ssd1306_WriteCommand(0x8D);
ssd1306_WriteCommand(0x14);
ssd1306_WriteCommand(0x20);
ssd1306_WriteCommand(0x00);
ssd1306_WriteCommand(0xA1);
ssd1306_WriteCommand(0xC8);
ssd1306_WriteCommand(0xDA);
ssd1306_WriteCommand(0x02);
ssd1306_WriteCommand(0x81);
ssd1306_WriteCommand(0x8F);
ssd1306_WriteCommand(0xD9);
ssd1306_WriteCommand(0xF1);
ssd1306_WriteCommand(0xDB);
ssd1306_WriteCommand(0x40);
ssd1306_WriteCommand(0xA4);
ssd1306_WriteCommand(0xA6);
ssd1306_WriteCommand(0x2E);
ssd1306_WriteCommand(0xAF);
ssd1306_ClearDisplay();
ssd1306_SetDisplay();
}
void ssd1306_WriteCommand(uint8_t command)
{
I2C1_open();
I2C1_startCondition();
I2C1_sendData((SSD1306_I2C_ADDR << 1) & ~0x01);
if (I2C1_getAckstatBit())
{
I2C1_stopCondition();
I2C1_close();
}
I2C1_sendData(0x00);
if (I2C1_getAckstatBit())
{
I2C1_stopCondition();
I2C1_close();
}
I2C1_sendData(command);
}
void ssd1306_WriteData(uint8_t *data, size_t size)
{
I2C1_open();
I2C1_startCondition();
I2C1_sendData((SSD1306_I2C_ADDR << 1) & ~0x01);
if (I2C1_getAckstatBit()){
I2C1_stopCondition();
I2C1_close();
}
I2C1_sendData(0x40);
if (I2C1_getAckstatBit()) {
I2C1_stopCondition();
I2C1_close();
}
for (size_t i = 0; i < size; i++) {
I2C1_sendData(data);
if (I2C1_getAckstatBit()) {
break;
}
}
}
void ssd1306_SetDisplay(void)
{
for (uint8_t page = 0; page < (SSD1306_HEIGHT / 8); page++)
{
ssd1306_WriteCommand(0xB0 + page);
ssd1306_WriteCommand(0x00);
ssd1306_WriteCommand(0x10);
ssd1306_WriteData(&buffer, SSD1306_WIDTH);
}
}
void ssd1306_SetDisplay_Horisontal(void)
{
ssd1306_WriteCommand(0x20); // Memory Addressing Mode
ssd1306_WriteCommand(0x00); // Horizontal Addressing Mode
ssd1306_WriteCommand(0x21); // column address
ssd1306_WriteCommand(0); // Start column
ssd1306_WriteCommand(SSD1306_WIDTH - 1);
ssd1306_WriteCommand(0x22); // Set page address
ssd1306_WriteCommand(0); // Start page
ssd1306_WriteCommand((SSD1306_HEIGHT / 8) - 1); // End page
ssd1306_WriteData(buffer, SSD1306_WIDTH * (SSD1306_HEIGHT / 8));
}
void ssd1306_SetDisplay_Vertical(void)
{
ssd1306_WriteCommand(0x20); // Memory Addressing Mode
ssd1306_WriteCommand(0x01); // Vertical Addressing Mode
ssd1306_WriteCommand(0x21); // column address
ssd1306_WriteCommand(0); // Start column
ssd1306_WriteCommand(SSD1306_WIDTH - 1);
ssd1306_WriteCommand(0x22); // Set page address
ssd1306_WriteCommand(0); // Start page
ssd1306_WriteCommand((SSD1306_HEIGHT / 8) - 1); // End page
ssd1306_WriteData(buffer, SSD1306_WIDTH * (SSD1306_HEIGHT / 8));
}
void ssd1306_ClearDisplay(void)
{
memset(buffer, 0, sizeof(buffer));
}
void ssd1306_EnableDisplay(uint8_t state)
{
ssd1306_WriteCommand(state ? 0xAF : 0xAE);
}
void ssd1306_SetContrast(uint8_t value)
{
ssd1306_WriteCommand(0x81);
ssd1306_WriteCommand(value);
}
void ssd1306_SetInversionMode(uint8_t setInversion)
{
ssd1306_WriteCommand(setInversion ? 0xA7 : 0xA6);
}
void ssd1306_SetEntireMode(uint8_t state)
{
ssd1306_WriteCommand(state ? 0xA5 : 0xA4);
}
void ssd1306_SetPixel(int16_t x, int16_t y, uint8_t color)
{
if (x < 0 || x >= SSD1306_WIDTH || y < 0 || y >= SSD1306_HEIGHT)
return;
uint16_t byteIndex = x + (y / 8) * SSD1306_WIDTH;
uint8_t bitMask = 1 << (y % 8);
if (color)
buffer |= bitMask;
else
buffer &= ~bitMask;
}
void ssd1306_SetCursor(uint8_t x, uint8_t y) {
ssd1306_WriteCommand(0x21); // Set column address
ssd1306_WriteCommand(x); // Start column
ssd1306_WriteCommand(127);// End column
ssd1306_WriteCommand(0x22); // Set page address
ssd1306_WriteCommand(y); // Start page
ssd1306_WriteCommand(0x07); // End page
}
void ssd1306_SetChar(char c) {
const uint8_t* charMap = _charASCIIMap;
uint8_t charBuffer;
if (c < 32 || c > 126) {
c = '?';
}
for (int i = 0; i < 5; i++) {
charBuffer = charMap;
}
charBuffer = 0x00;
ssd1306_WriteData(charBuffer, sizeof(charBuffer));
}
void ssd1306_PutString(const char* str) {
while (*str) {
ssd1306_SetChar(*str++);
}
}
void ssd1306_DemoAnimation(void) {
ssd1306_ClearDisplay();
for (int i = 0; i < 120; i += 5)
{
ssd1306_ClearDisplay();
for (int x = i; x < i + 30 && x < 128; x++)
{
for (int y = 5; y < 25; y++)
{
ssd1306_SetPixel(x, y, 1);
}
}
ssd1306_SetDisplay();
}
ssd1306_ClearDisplay();
ssd1306_SetCursor(15, 0);
ssd1306_PutString("Hello, world!");
}
学习一下驱动方法 这些常用的模块驱动,是必须要掌握的。 这个示例代码看起来很不错,你已经成功地将PIC18F47Q10与SSD1306 OLED显示屏通过I2C连接起来了。动画演示部分应该能很好地展示基本的绘图功能。
页:
[1]