-----------------------------------------------------------------------------------------------H-----------------------------------------------------------------------------------------------
#ifndef __MY_OLED__
#define __MY_OLED__
#include "gd32f20x_gpio.h"
#include "my_systick.h"
#include "stdint.h"
#include "string.h"
#include "lcdfont.h"
#define LCD_LED(x) gpio_bit_write(GPIOC,GPIO_PIN_13,x);
#define LCD_RS_CLR gpio_bit_reset(GPIOC,GPIO_PIN_7)
#define LCD_RST_CLR gpio_bit_reset(GPIOA,GPIO_PIN_11)
#define LCD_CS_CLR gpio_bit_reset(GPIOC,GPIO_PIN_6)
#define LCD_WR_CLR gpio_bit_reset(GPIOA,GPIO_PIN_8)
#define LCD_RD_CLR gpio_bit_reset(GPIOA,GPIO_PIN_12)
#define LCD_RST_SET gpio_bit_set(GPIOA, GPIO_PIN_11)
#define LCD_WR_SET gpio_bit_set(GPIOA, GPIO_PIN_8)
#define LCD_CS_SET gpio_bit_set(GPIOC, GPIO_PIN_6)
#define LCD_RS_SET gpio_bit_set(GPIOC, GPIO_PIN_7)
#define LCD_RD_SET gpio_bit_set(GPIOA, GPIO_PIN_12)
#define DATAOUT(x) gpio_port_write(GPIOB,x&0xFFFF) //数据输出
#define LCD_DATA_OUT() {gpio_init(GPIOB,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,0xFFFF);}
#define LCD_DATA_IN() {gpio_init(GPIOB,GPIO_MODE_IPU,GPIO_OSPEED_50MHZ,0xFFFF);}
#define DATAIN gpio_input_port_get(GPIOB) //数据输入
//扫描方向定义
#define L2R_U2D 0x00 //从左到右,从上到下(正向,0度)
#define L2R_D2U 0x80 //从左到右,从下到上
#define R2L_U2D 0x40 //从右到左,从上到下
#define R2L_D2U 0xc0 //从右到左,从下到上(旋转180度)
#define U2D_L2R 0x20 //从上到下,从左到右
#define U2D_R2L 0x60 //从上到下,从右到左(旋转90度)
#define D2U_L2R 0xa0 //从下到上,从左到右(旋转270度)
#define D2U_R2L 0xe0 //从下到上,从右到左
#define DFT_SCAN_DIR D2U_L2R //默认的扫描方
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define BRED 0XF81F
#define GRED 0XFFE0
#define GBLUE 0X07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define GREEN 0x07E0
#define CYAN 0x7FFF
#define YELLOW 0xFFE0
#define BROWN 0XBC40 //棕色
#define BRRED 0XFC07 //棕红色
#define GRAY 0X8430 //灰色
//LCD重要参数集
typedef struct
{
uint16_t width; //LCD 宽度
uint16_t height; //LCD 高度
uint16_t id; //LCD ID
}_lcd_dev;
void my_oled_init(void);
void LCD_Clear(uint16_t color);
void LCD_DrawPoint(uint16_t x,uint16_t y,uint16_t color);
uint16_t LCD_ReadPoint(uint16_t x,uint16_t y);
void LCD_SetCursor(uint16_t x,uint16_t y);
void LCD_ShowPicture(uint16_t x,uint16_t y,uint16_t length,uint16_t width,const uint8_t pic[]);
void LCD_ShowChar(uint16_t x,uint16_t y,uint8_t num,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode);
#endif
-----------------------------------------------------------------------------------------------C-----------------------------------------------------------------------------------------------
#include "my_oled.h"
_lcd_dev lcddev;
/*
static void LCD_WR_REG(uint16_t reg)
{
LCD_RS_CLR;
LCD_CS_CLR;
DATAOUT(reg);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
*/
__asm static void LCD_WR_REG(uint16_t reg)
{
PUSH {r4-r6,lr}
ldr R5, =0x40011014
ldr R1, =0x80
str R1, [R5]
ldr R5, =0x40011014
ldr R1, =0x40
str R1, [R5]
nop
ldr R5, =0x40010C0C
str R0, [R5]
nop
ldr R5, =0x40010814
ldr R1, =0x100
str R1, [R5]
ldr R5, =0x40010810
ldr R1, =0x100
str R1, [R5]
ldr R5, =0x40011010
ldr R1, =0x40
str R1, [R5]
POP {r4-r6,lr}
BX LR
}
static void Set_Dir(uint8_t dir)
{
if((dir>>4)%4)
{
lcddev.width=320;
lcddev.height=240;
}else
{
lcddev.width=240;
lcddev.height=320;
}
}
static uint16_t LCD_RD_DATA(void)
{
uint16_t data=0;
LCD_DATA_IN();
LCD_RS_SET;
LCD_CS_CLR;
LCD_RD_CLR;
data=DATAIN;
LCD_RD_SET;
LCD_CS_SET;
LCD_DATA_OUT();
return data;
}
/*
static void LCD_WR_DATA(uint16_t data)
{
LCD_RS_SET;
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
*/
__asm static void LCD_WR_DATA(uint16_t data)
{
PUSH {r4-r6,lr}
ldr R5, =0x40011010
ldr R1, =0x80
str R1, [R5]
ldr R5, =0x40011014
ldr R1, =0x40
str R1, [R5]
nop
ldr R5, =0x40010C0C
str R0, [R5]
nop
ldr R5, =0x40010814
ldr R1, =0x100
str R1, [R5]
ldr R5, =0x40010810
ldr R1, =0x100
str R1, [R5]
ldr R5, =0x40011010
ldr R1, =0x40
str R1, [R5]
POP {r4-r6,lr}
BX LR
}
//写LCD数据
//data:要写入的值
void LCD_WR_data(uint16_t data)
{
LCD_RS_SET;
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
/******************************************************************************
函数说明:设置起始和结束地址
入口数据:x1,x2 设置列的起始和结束地址
y1,y2 设置行的起始和结束地址
返回值: 无
******************************************************************************/
void LCD_Address_Set(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2)
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_data(x1>>8);
LCD_WR_data(x1&0xff);
LCD_WR_data(x2>>8);
LCD_WR_data(x2&0xff);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_data(y1>>8);
LCD_WR_data(y1&0xff);
LCD_WR_data(y2>>8);
LCD_WR_data(y2&0xff);
LCD_WR_REG(0x2c);//储存器写
}
void my_oled_init(void)
{
LCD_RST_CLR;
delay_1ms(200);
LCD_RST_SET;
delay_1ms(50);
Set_Dir(DFT_SCAN_DIR);
LCD_WR_REG(0XD3);
lcddev.id=LCD_RD_DATA(); //dummy read
lcddev.id=LCD_RD_DATA(); //读到0X00
lcddev.id=LCD_RD_DATA(); //读取93
lcddev.id<<=8;
lcddev.id|=LCD_RD_DATA(); //读取41
LCD_WR_REG(0xCF);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0xC1);
LCD_WR_DATA(0X30);
LCD_WR_REG(0xED);
LCD_WR_DATA(0x64);
LCD_WR_DATA(0x03);
LCD_WR_DATA(0X12);
LCD_WR_DATA(0X81);
LCD_WR_REG(0xE8);
LCD_WR_DATA(0x85);
LCD_WR_DATA(0x10);
LCD_WR_DATA(0x7A);
LCD_WR_REG(0xCB);
LCD_WR_DATA(0x39);
LCD_WR_DATA(0x2C);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x34);
LCD_WR_DATA(0x02);
LCD_WR_REG(0xF7);
LCD_WR_DATA(0x20);
LCD_WR_REG(0xEA);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_REG(0xC0); //Power control
LCD_WR_DATA(0x1B); //VRH[5:0]
LCD_WR_REG(0xC1); //Power control
LCD_WR_DATA(0x01); //SAP[2:0];BT[3:0]
LCD_WR_REG(0xC5); //VCM control
LCD_WR_DATA(0x30); //3F
LCD_WR_DATA(0x30); //3C
LCD_WR_REG(0xC7); //VCM control2
LCD_WR_DATA(0XB7);
LCD_WR_REG(0x36); // Memory Access Control
LCD_WR_DATA(0x08|DFT_SCAN_DIR);
LCD_WR_REG(0x3A);
LCD_WR_DATA(0x55);
LCD_WR_REG(0xB1);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x1A);
LCD_WR_REG(0xB6); // Display Function Control
LCD_WR_DATA(0x0A);
LCD_WR_DATA(0xA2);
LCD_WR_REG(0xF2); // 3Gamma Function Disable
LCD_WR_DATA(0x00);
LCD_WR_REG(0x26); //Gamma curve selected
LCD_WR_DATA(0x01);
LCD_WR_REG(0xE0); //Set Gamma
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x2A);
LCD_WR_DATA(0x28);
LCD_WR_DATA(0x08);
LCD_WR_DATA(0x0E);
LCD_WR_DATA(0x08);
LCD_WR_DATA(0x54);
LCD_WR_DATA(0XA9);
LCD_WR_DATA(0x43);
LCD_WR_DATA(0x0A);
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_REG(0XE1); //Set Gamma
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x15);
LCD_WR_DATA(0x17);
LCD_WR_DATA(0x07);
LCD_WR_DATA(0x11);
LCD_WR_DATA(0x06);
LCD_WR_DATA(0x2B);
LCD_WR_DATA(0x56);
LCD_WR_DATA(0x3C);
LCD_WR_DATA(0x05);
LCD_WR_DATA(0x10);
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x3F);
LCD_WR_DATA(0x3F);
LCD_WR_DATA(0x0F);
LCD_WR_REG(0x2B);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x01);
LCD_WR_DATA(0x3f);
LCD_WR_REG(0x2A);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0xef);
LCD_WR_REG(0x11); //Exit Sleep
delay_1ms(120);
LCD_WR_REG(0x29); //display on
LCD_Clear(WHITE);
}
/******************************************************************************
函数说明:设置光标位置
入口数据:x,y 光标位置
返回值: 无
******************************************************************************/
void LCD_SetCursor(uint16_t x,uint16_t y)
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_data(x>>8);
LCD_WR_data(x&0xff);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_data(y>>8);
LCD_WR_data(y&0xff);
}
void LCD_Clear(uint16_t color)
{
uint16_t i,j;
LCD_Address_Set(0,0,lcddev.width-1,lcddev.height-1);//设置显示范围
for(i=0;i<lcddev.width;i++)
{
for(j=0;j<lcddev.height;j++)
{
LCD_WR_DATA(color);
}
}
}
/******************************************************************************
函数说明:在指定位置画点
入口数据:x,y 画点坐标
color 点的颜色
返回值: 无
******************************************************************************/
void LCD_DrawPoint(uint16_t x,uint16_t y,uint16_t color)
{
LCD_Address_Set(x,y,x,y);//设置光标位置
LCD_WR_DATA(color);
}
//读取个某点的颜色值
//x,y:坐标
//返回值:此点的颜色
uint16_t LCD_ReadPoint(uint16_t x,uint16_t y)
{
uint16_t r=0,g=0,b=0;
LCD_SetCursor(x,y);
LCD_WR_REG(0X2E);
r=LCD_RD_DATA();//dummy read
r=LCD_RD_DATA();//实际坐标颜色
b=LCD_RD_DATA();
g=r&0XFF;
g<<=8;
return (((r>>11)<<11)|((g>>10)<<5)|(b>>11));
}
/******************************************************************************
函数说明:显示单个字符
入口数据:x,y显示坐标
num 要显示的字符
fc 字的颜色
bc 字的背景色
sizey 字号
mode: 0非叠加模式 1叠加模式
返回值: 无
******************************************************************************/
void LCD_ShowChar(uint16_t x,uint16_t y,uint8_t num,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode)
{
uint8_t temp,sizex,t,m=0;
uint16_t i,TypefaceNum;//一个字符所占字节大小
uint16_t x0=x;
sizex=sizey/2;
TypefaceNum=(sizex/8+((sizex%8)?1:0))*sizey;
num=num-' '; //得到偏移后的值
LCD_Address_Set(x,y,x+sizex-1,y+sizey-1); //设置光标位置
for(i=0;i<TypefaceNum;i++)
{
if(sizey==12)temp=ascii_1206[num][i]; //调用6x12字体
else if(sizey==16)temp=ascii_1608[num][i]; //调用8x16字体
else if(sizey==24)temp=ascii_2412[num][i]; //调用12x24字体
else if(sizey==32)temp=ascii_3216[num][i]; //调用16x32字体
else return;
for(t=0;t<8;t++)
{
if(!mode)//非叠加模式
{
if(temp&(0x01<<t))LCD_WR_DATA(fc);
else LCD_WR_DATA(bc);
m++;
if(m%sizex==0)
{
m=0;
break;
}
}
else//叠加模式
{
if(temp&(0x01<<t))LCD_DrawPoint(x,y,fc);//画一个点
x++;
if((x-x0)==sizex)
{
x=x0;
y++;
break;
}
}
}
}
}
/******************************************************************************
函数说明:显示数字
入口数据:m底数,n指数
返回值: 无
******************************************************************************/
uint32_t mypow(uint8_t m,uint8_t n)
{
uint32_t result=1;
while(n--)result*=m;
return result;
}
/******************************************************************************
函数说明:显示整数变量
入口数据:x,y显示坐标
num 要显示整数变量
len 要显示的位数
fc 字的颜色
bc 字的背景色
sizey 字号
返回值: 无
******************************************************************************/
void LCD_ShowIntNum(uint16_t x,uint16_t y,uint16_t num,uint8_t len,uint16_t fc,uint16_t bc,uint8_t sizey)
{
uint8_t t,temp;
uint8_t enshow=0;
uint8_t sizex=sizey/2;
for(t=0;t<len;t++)
{
temp=(num/mypow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
LCD_ShowChar(x+t*sizex,y,' ',fc,bc,sizey,0);
continue;
}else enshow=1;
}
LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0);
}
}
/******************************************************************************
函数说明:在指定区域填充颜色
入口数据:xsta,ysta 起始坐标
xend,yend 终止坐标
color 要填充的颜色
返回值: 无
******************************************************************************/
void LCD_Fill(uint16_t xsta,uint16_t ysta,uint16_t xend,uint16_t yend,uint16_t color)
{
uint16_t i,j;
LCD_Address_Set(xsta,ysta,xend-1,yend-1);//设置显示范围
for(i=ysta;i<yend;i++)
{
for(j=xsta;j<xend;j++)
{
LCD_WR_DATA(color);
}
}
}
/******************************************************************************
函数说明:显示图片
入口数据:x,y起点坐标
length 图片长度
width 图片宽度
pic[] 图片数组
返回值: 无
******************************************************************************/
void LCD_ShowPicture(uint16_t x,uint16_t y,uint16_t length,uint16_t width,const uint8_t pic[])
{
uint8_t picH,picL;
uint16_t i,j;
uint32_t k=0;
LCD_Address_Set(x,y,x+length-1,y+width-1);
for(i=0;i<length;i++)
{
for(j=0;j<width;j++)
{
picH=pic[k*2];
picL=pic[k*2+1];
LCD_WR_DATA((picH<<8|picL));
k++;
}
}
}