motor_f103/User/board/ssd1306_oled.c

156 lines
4.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file ssd1306_oled.c
* @author xushenghao
* @brief SSD1306 OLED display driver
* @version 0.1
* @note PB13-SCK PB12-SDA
*/
#include "ssd1306_oled.h"
#include "ssd1306_oled.h"
static i2c_t *ssd1306_oled;
static uint8_t buffer[SSD1306_WIDTH * SSD1306_HEIGHT / 8]; // 定义屏幕缓冲区
static void ssd1306_write_command(uint8_t command)
{
uint8_t data[2];
data[0] = SSD1306_CMD_SET_LOW_COLUMN; // Co = 0, D/C# = 0
data[1] = command;
ssd1306_oled->interface.start(ssd1306_oled);
ssd1306_oled->interface.write_byte(ssd1306_oled, SSD1306_I2C_ADDRESS);
ssd1306_oled->interface.wait_ack(ssd1306_oled);
ssd1306_oled->interface.write_byte(ssd1306_oled, data[0]);
ssd1306_oled->interface.wait_ack(ssd1306_oled);
ssd1306_oled->interface.write_byte(ssd1306_oled, data[1]);
ssd1306_oled->interface.wait_ack(ssd1306_oled);
ssd1306_oled->interface.stop(ssd1306_oled);
}
static void ssd1306_write_data(uint8_t data)
{
uint8_t buffer[2];
buffer[0] = SSD1306_CMD_SET_START_LINE; // Co = 0, D/C# = 1
buffer[1] = data;
ssd1306_oled->interface.start(ssd1306_oled);
ssd1306_oled->interface.write_byte(ssd1306_oled, SSD1306_I2C_ADDRESS);
ssd1306_oled->interface.wait_ack(ssd1306_oled);
ssd1306_oled->interface.write_byte(ssd1306_oled, buffer[0]);
ssd1306_oled->interface.wait_ack(ssd1306_oled);
ssd1306_oled->interface.write_byte(ssd1306_oled, buffer[1]);
ssd1306_oled->interface.wait_ack(ssd1306_oled);
ssd1306_oled->interface.stop(ssd1306_oled);
}
static void ssd1306_test(void)
{
}
void ssd1306_init(void)
{
i2c_gpio_group_t gpios;
gpios.scl = gpio_create(SSD1306_SCK_PORT, SSD1306_SCK_PIN);
gpios.sda = gpio_create(SSD1306_SDA_PORT, SSD1306_SDA_PIN);
ssd1306_oled = i2c_create(gpios, 0);
ssd1306_write_command(SSD1306_CMD_DISPLAY_OFF);
ssd1306_write_command(SSD1306_CMD_SET_DISPLAY_CLOCK_DIV);
ssd1306_write_command(0x80);
ssd1306_write_command(SSD1306_CMD_SET_MULTIPLEX);
ssd1306_write_command(SSD1306_HEIGHT - 1);
ssd1306_write_command(SSD1306_CMD_SET_DISPLAY_OFFSET);
ssd1306_write_command(0x00);
ssd1306_write_command(SSD1306_CMD_SET_START_LINE | 0x00);
ssd1306_write_command(SSD1306_CMD_CHARGE_PUMP);
ssd1306_write_command(0x14);
ssd1306_write_command(SSD1306_CMD_MEMORY_MODE);
ssd1306_write_command(0x00);
ssd1306_write_command(SSD1306_CMD_SEG_REMAP | 0x01);
ssd1306_write_command(SSD1306_CMD_COM_SCAN_DEC);
ssd1306_write_command(SSD1306_CMD_SET_COM_PINS);
ssd1306_write_command(0x12);
ssd1306_write_command(SSD1306_CMD_SET_CONTRAST);
ssd1306_write_command(0xCF);
ssd1306_write_command(SSD1306_CMD_SET_PRECHARGE);
ssd1306_write_command(0xF1);
ssd1306_write_command(SSD1306_CMD_SET_VCOM_DETECT);
ssd1306_write_command(0x40);
ssd1306_write_command(SSD1306_CMD_DISPLAY_ALL_ON_RESUME);
ssd1306_write_command(SSD1306_CMD_NORMAL_DISPLAY);
ssd1306_write_command(SSD1306_CMD_DISPLAY_ON);
ssd1306_test();
}
void ssd1306_display_on(void)
{
ssd1306_write_command(SSD1306_CMD_DISPLAY_ON);
}
void ssd1306_display_off(void)
{
ssd1306_write_command(SSD1306_CMD_DISPLAY_OFF);
}
void ssd1306_clear(void)
{
for (uint16_t i = 0; i < SSD1306_WIDTH * SSD1306_HEIGHT / 8; i++)
{
ssd1306_write_data(0x00);
}
}
/**
* @brief 在SSD1306屏幕上绘制一个像素点
*
* 在SSD1306 OLED显示屏上绘制一个像素点如果指定位置超出屏幕范围则不执行任何操作。
*
* @param x 像素点的x坐标
* @param y 像素点的y坐标
* @param color 像素点的颜色,非零值表示绘制像素点,零值表示清除像素点
*/
void ssd1306_draw_pixel(uint8_t x, uint8_t y, uint8_t color)
{
if (x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT)
{
return;
}
if (color)
{
buffer[x + (y / 8) * SSD1306_WIDTH] |= (1 << (y % 8));
}
else
{
buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8));
}
}
/**
* @brief 更新SSD1306 OLED显示屏的内容
*
* 此函数将缓冲区中的数据写入SSD1306 OLED显示屏从而更新显示内容。
*
* 首先,通过发送命令设置列地址和页地址,然后将缓冲区中的数据逐行写入显示屏。
*
* @note 在调用此函数之前,需要将需要显示的数据写入缓冲区。
*/
void ssd1306_update_screen(void)
{
for (uint8_t i = 0; i < SSD1306_HEIGHT / 8; i++)
{
ssd1306_write_command(SSD1306_CMD_COLUMN_ADDR);
ssd1306_write_command(0);
ssd1306_write_command(SSD1306_WIDTH - 1);
ssd1306_write_command(SSD1306_CMD_PAGE_ADDR);
ssd1306_write_command(i);
ssd1306_write_command(i);
for (uint8_t j = 0; j < SSD1306_WIDTH; j++)
{
ssd1306_write_data(buffer[j + i * SSD1306_WIDTH]);
}
}
}