shuichan_old/V1.5/STM32F103_App1/HardWare/OLED/oled.c

314 lines
9.0 KiB
C
Raw Normal View History

/* oled.c - 128x64 OLED + <20><><EFBFBD><EFBFBD>Ѷ GB2312 <20>ֿ<EFBFBD> IC <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>GPIO ģ<><C4A3> SPI<50><49>
* <EFBFBD><EFBFBD>ֲ<EFBFBD>ԡ<EFBFBD>485ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD>CRC<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> oledisp.c<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>
* CLK=PC12 MOSI=PC9 DC=PC8 CS1=PC7 FSO=PC6 CS2=PB15 */
#include "oled.h"
#include <string.h>
#define OLED_CLK_PORT GPIOC
#define OLED_CLK_PIN GPIO_PIN_12
#define OLED_MOSI_PORT GPIOC
#define OLED_MOSI_PIN GPIO_PIN_9
#define OLED_DC_PORT GPIOC
#define OLED_DC_PIN GPIO_PIN_8
#define OLED_CS1_PORT GPIOC
#define OLED_CS1_PIN GPIO_PIN_7
#define OLED_FSO_PORT GPIOC
#define OLED_FSO_PIN GPIO_PIN_6
#define OLED_CS2_PORT GPIOB
#define OLED_CS2_PIN GPIO_PIN_15
#define lcd_cs1(a) HAL_GPIO_WritePin(OLED_CS1_PORT, OLED_CS1_PIN, (GPIO_PinState)(a))
#define lcd_dc(a) HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, (GPIO_PinState)(a))
#define lcd_mosi(a) HAL_GPIO_WritePin(OLED_MOSI_PORT, OLED_MOSI_PIN, (GPIO_PinState)(a))
#define lcd_clk(a) HAL_GPIO_WritePin(OLED_CLK_PORT, OLED_CLK_PIN, (GPIO_PinState)(a))
#define rom_cs2(a) HAL_GPIO_WritePin(OLED_CS2_PORT, OLED_CS2_PIN, (GPIO_PinState)(a))
#define ROM_OUT HAL_GPIO_ReadPin(OLED_FSO_PORT, OLED_FSO_PIN)
static uint8_t s_row = 0; /* <20><>ǰҳ<C7B0><D2B3>ַ<EFBFBD><D6B7>16px <20><> <20><> 2<><32> */
static uint8_t s_col = 0; /* <20><>ǰ<EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD>أ<EFBFBD> */
/*==== FSO <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD>ʱΪ<CAB1><CEAA><EFBFBD>룩====*/
static void fso_input(void)
{
GPIO_InitTypeDef g = {0};
g.Pin = OLED_FSO_PIN;
g.Mode = GPIO_MODE_INPUT;
g.Pull = GPIO_NOPULL;
HAL_GPIO_Init(OLED_FSO_PORT, &g);
}
static void fso_output(void)
{
GPIO_InitTypeDef g = {0};
g.Pin = OLED_FSO_PIN;
g.Mode = GPIO_MODE_OUTPUT_PP;
g.Pull = GPIO_PULLUP;
g.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(OLED_FSO_PORT, &g);
}
/*==== GPIO <20><>ʼ<EFBFBD><CABC> ====*/
static void oled_gpio_init(void)
{
GPIO_InitTypeDef g = {0};
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/* <20><><EFBFBD>úÿ<C3BA><C3BF>е<EFBFBD>ƽ<EFBFBD>ٿ<EFBFBD><D9BF><EFBFBD><EFBFBD><EFBFBD><ECA3AC><EFBFBD><EFBFBD>ë<EFBFBD><C3AB> */
HAL_GPIO_WritePin(OLED_CLK_PORT, OLED_CLK_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(OLED_MOSI_PORT, OLED_MOSI_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(OLED_CS1_PORT, OLED_CS1_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(OLED_CS2_PORT, OLED_CS2_PIN, GPIO_PIN_SET);
g.Mode = GPIO_MODE_OUTPUT_PP;
g.Pull = GPIO_PULLUP;
g.Speed = GPIO_SPEED_FREQ_LOW;
g.Pin = OLED_CLK_PIN; HAL_GPIO_Init(OLED_CLK_PORT, &g);
g.Pin = OLED_MOSI_PIN; HAL_GPIO_Init(OLED_MOSI_PORT, &g);
g.Pin = OLED_DC_PIN; HAL_GPIO_Init(OLED_DC_PORT, &g);
g.Pin = OLED_CS1_PIN; HAL_GPIO_Init(OLED_CS1_PORT, &g);
g.Pin = OLED_CS2_PIN; HAL_GPIO_Init(OLED_CS2_PORT, &g);
fso_output();
}
/*==== д<>ֽڵ<D6BD><DAB5><EFBFBD>Ļ<EFBFBD><C4BB>DC=0 ָ<><D6B8> / DC=1 <20><><EFBFBD>ݣ<EFBFBD>====*/
static void oled_write(uint8_t dc, uint8_t dat)
{
lcd_dc(dc);
lcd_cs1(0);
for (int i = 0; i < 8; i++) {
lcd_clk(0);
lcd_mosi(dat & 0x80);
lcd_clk(1);
dat <<= 1;
}
lcd_dc(1);
lcd_cs1(1);
}
/*==== <20><><EFBFBD><EFBFBD>ҳ/<2F>е<EFBFBD>ַ ====*/
static void lcd_address(uint8_t page, uint8_t column)
{
oled_write(0, 0xb0 + column); /* ҳ<><D2B3>ַ */
oled_write(0, ((page & 0xf0) >> 4) | 0x10); /* <20>е<EFBFBD>ַ<EFBFBD><D6B7> 4 λ */
oled_write(0, (page & 0x0f)); /* <20>е<EFBFBD>ַ<EFBFBD><D6B7> 4 λ */
}
/*==== <20><><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>Ԥ<EFBFBD><D4A4>ʱ<EFBFBD><CAB1><EFBFBD>ã<EFBFBD>====*/
void oled_off(void)
{
oled_write(0, 0xAE); /* display off */
}
/*==== ȫ<><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ====*/
void oled_clear(void)
{
lcd_cs1(0);
rom_cs2(1);
for (uint8_t i = 0; i < 8; i++) {
oled_write(0, 0xb0 + i);
oled_write(0, 0x00);
oled_write(0, 0x10);
for (uint8_t j = 0; j < 128; j++) oled_write(1, 0x00);
}
lcd_cs1(1);
}
/*==== <20><>Ļ<EFBFBD><C4BB>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>SSD1306 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>====*/
void oled_init(void)
{
HAL_Delay(400); /* <20><><EFBFBD><EFBFBD>Ļ/<2F>ֿ<EFBFBD><D6BF>ϵ<EFBFBD><CFB5>ȶ<EFBFBD> */
oled_gpio_init();
lcd_cs1(0);
rom_cs2(1);
oled_write(0, 0xAE); /* display off */
oled_write(0, 0x20); /* Ѱַģʽ */
oled_write(0, 0x10); /* ˮƽѰַ */
oled_write(0, 0xb0);
oled_write(0, 0xc8); /* COM ɨ<><EFBFBD><E8B7BD> */
oled_write(0, 0x00);
oled_write(0, 0x10);
oled_write(0, 0x40); /* <20><>ʼ<EFBFBD><CABC> */
oled_write(0, 0x81); /* <20>Աȶ<D4B1> */
oled_write(0, 0xFF);
oled_write(0, 0xa1); /* <20><><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3> */
oled_write(0, 0xa6); /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ */
oled_write(0, 0xa8); /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
oled_write(0, 0x3F);
oled_write(0, 0xa4);
oled_write(0, 0xd3); /* <20><>ʾƫ<CABE><C6AB> */
oled_write(0, 0x00);
oled_write(0, 0xd5); /* ʱ<>ӷ<EFBFBD>Ƶ */
oled_write(0, 0xf0);
oled_write(0, 0xd9); /* Ԥ<><D4A4><EFBFBD><EFBFBD> */
oled_write(0, 0x22);
oled_write(0, 0xda); /* COM Ӳ<><D3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
oled_write(0, 0x12);
oled_write(0, 0xdb); /* VCOMH */
oled_write(0, 0x20);
oled_write(0, 0x8d); /* DC-DC */
oled_write(0, 0x14);
oled_write(0, 0xaf); /* display on */
lcd_cs1(1);
oled_clear();
}
/*==== <20><>ʾ 16x16 <20><><EFBFBD>󣨺<EFBFBD><F3A3A8BA>֣<EFBFBD>====*/
static void display_graphic_16x16(uint8_t page, uint8_t column, const uint8_t *dp)
{
lcd_cs1(0);
rom_cs2(1);
for (uint8_t j = 2; j > 0; j--) {
lcd_address(column, page);
for (uint8_t i = 0; i < 16; i++) oled_write(1, *dp++);
page++;
}
lcd_cs1(1);
}
/*==== <20><>ʾ 8x16 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ASCII<49><49>====*/
static void display_graphic_8x16(uint8_t page, uint8_t column, const uint8_t *dp)
{
lcd_cs1(0);
for (uint8_t j = 2; j > 0; j--) {
lcd_address(column, page);
for (uint8_t i = 0; i < 8; i++) oled_write(1, *dp++);
page++;
}
lcd_cs1(1);
}
/*==== <20>ֿ<EFBFBD> IC д<>ֽڣ<D6BD>ָ<EFBFBD><D6B8>/<2F><>ַ<EFBFBD><D6B7>====*/
static void rom_write_byte(uint8_t dat)
{
for (int i = 0; i < 8; i++) {
lcd_mosi(dat & 0x80);
dat <<= 1;
lcd_clk(0);
lcd_clk(1);
}
}
/*==== <20>ֿ<EFBFBD> IC <20><>һ<EFBFBD>ֽ<EFBFBD> ====*/
static uint8_t rom_read_byte(void)
{
uint8_t ret = 0;
lcd_clk(1);
fso_input();
for (int i = 0; i < 8; i++) {
lcd_clk(0);
ret <<= 1;
if (ROM_OUT) ret |= 1;
lcd_clk(1);
}
fso_output();
return ret;
}
/*==== <20><><EFBFBD>ֿ<EFBFBD> IC <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> DataLen <20>ֽ<EFBFBD> ====*/
static void rom_read_n(uint8_t ah, uint8_t am, uint8_t al, uint8_t *buf, uint8_t len)
{
rom_cs2(0);
lcd_cs1(1);
lcd_clk(0);
rom_write_byte(0x03); /* <20><>ָ<EFBFBD><D6B8> */
rom_write_byte(ah);
rom_write_byte(am);
rom_write_byte(al);
for (uint8_t i = 0; i < len; i++) buf[i] = rom_read_byte();
rom_cs2(1);
}
/*==== <20><>λ<EFBFBD><CEBB>row 0~3<><33>16px <20>У<EFBFBD><D0A3><EFBFBD>col8 Ϊ 8 <20><><EFBFBD>ص<EFBFBD>λ ====*/
void oled_locate(uint8_t row, uint8_t col8)
{
s_row = row * 2;
s_col = col8 * 8;
}
/*==== <20><>ʾ GBK <20>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>16x16 <20><><EFBFBD><EFBFBD> / 8x16 ASCII<49><49><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBBBBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѷ<EFBFBD>ֿ<EFBFBD><D6BF>ֲᣩ====*/
void oled_print(const char *s)
{
uint8_t fontbuf[32];
uint8_t y = s_row;
uint8_t x = s_col;
const uint8_t *text = (const uint8_t *)s;
uint32_t fontaddr;
s_col += strlen(s) * 8; /* λ<><CEBB><EFBFBD>Լӣ<D4BC><D3A3><EFBFBD> 8px/<2F>ַ<EFBFBD><D6B7>ƣ<EFBFBD> */
uint8_t i = 0;
while (text[i] > 0x00) {
if ((text[i] >= 0xb0 && text[i] <= 0xf7) && text[i+1] >= 0xa1) {
/* GB2312 <20><><EFBFBD>֣<EFBFBD>Address = ((MSB-0xB0)*94 + (LSB-0xA1) + 846) * 32 */
fontaddr = (text[i] - 0xb0) * 94;
fontaddr += (text[i+1] - 0xa1) + 846;
fontaddr *= 32;
rom_read_n((uint8_t)(fontaddr >> 16), (uint8_t)(fontaddr >> 8),
(uint8_t)fontaddr, fontbuf, 32);
display_graphic_16x16(y, x, fontbuf);
i += 2;
x += 16;
}
else if ((text[i] >= 0xa1 && text[i] <= 0xa3) && text[i+1] >= 0xa1) {
/* GB2312 ȫ<>Ƿ<EFBFBD><C7B7>ţ<EFBFBD>Address = ((MSB-0xA1)*94 + (LSB-0xA1)) * 32 */
fontaddr = (text[i] - 0xa1) * 94;
fontaddr += (text[i+1] - 0xa1);
fontaddr *= 32;
rom_read_n((uint8_t)(fontaddr >> 16), (uint8_t)(fontaddr >> 8),
(uint8_t)fontaddr, fontbuf, 32);
display_graphic_16x16(y, x, fontbuf);
i += 2;
x += 16;
}
else if (text[i] >= 0x20 && text[i] <= 0x7e) {
/* ASCII 8x16<31><36>Address = (char-0x20)*16 + 0x3CF80 */
fontaddr = (text[i] - 0x20) * 16 + 0x3cf80;
rom_read_n((uint8_t)(fontaddr >> 16), (uint8_t)(fontaddr >> 8),
(uint8_t)fontaddr, fontbuf, 16);
display_graphic_8x16(y, x, fontbuf);
i += 1;
x += 8;
}
else {
i++;
}
}
}
/*==== <20><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD> px <20><><EFBFBD><EFBFBD> ====*/
void oled_xoff(uint8_t px)
{
s_col += px;
}
/*==== <20>ı<EFBFBD><C4B1><EFBFBD><EFBFBD>ؿ<EFBFBD><D8BF>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD><><C8AB> 16px<70><78>ASCII 8px ====*/
uint8_t oled_text_w(const char *s)
{
const uint8_t *p = (const uint8_t *)s;
uint32_t w = 0;
while (*p) {
if (p[0] >= 0xa1 && p[1] >= 0xa1) { w += 16; p += 2; }
else { w += 8; p += 1; }
}
return (uint8_t)(w > 128 ? 128 : w);
}
/*==== <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؿ<EFBFBD><D8BF>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD> 128px <20>ÿո<C3BF><D5B8><EFBFBD><EFBFBD><EFBFBD><EBA3A8><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD>ݣ<EFBFBD>====*/
void oled_print_line(const char *s)
{
const uint8_t *p = (const uint8_t *)s;
uint32_t w = 0;
while (*p) {
if (p[0] >= 0xa1 && p[1] >= 0xa1) { w += 16; p += 2; } /* <20><><EFBFBD><EFBFBD><><C8AB> */
else { w += 8; p += 1; } /* ASCII */
}
oled_print(s);
while (w < 128) { oled_print(" "); w += 8; }
}