[GD32L233C] + 6.使用软件SPI驱动OLED
[复制链接]
本帖最后由 chrisrh 于 2022-2-19 16:05 编辑
使用IO模拟SPI驱动0.96'的OLED
查看数据手册:
选用带有硬件 SPI1 功能的PB12/PB13/PB14/PB15等IO口
采用软件模拟IO的方式驱动:
RST_Pin GPIO_PIN_15 //RES PB15
DC_Pin GPIO_PIN_12 //DC PB12
D0_Pin GPIO_PIN_13 //SCL PB13
D1_Pin GPIO_PIN_14 //SDA PB14
①宏定义IO的引脚
//////////////////////宏定义GD32L233使用PB12/13/14/15//////////////////////////
#define OLED_RCC RCU_GPIOB
#define OLED_PORT GPIOB
#define RST_Pin GPIO_PIN_15 //RES PB15
#define DC_Pin GPIO_PIN_12 //DC PB12
#define D0_Pin GPIO_PIN_13 //SCL PB13
#define D1_Pin GPIO_PIN_14 //SDA PB14
#define OLED_RST_Clr() gpio_bit_reset(OLED_PORT,RST_Pin)//(GPIO_BC(GPIOB) = RST_Pin)////GPIOB->BRR=1<<RST //PBout(RST)=0 //RST IO口输出低电平
#define OLED_RST_Set() gpio_bit_set(OLED_PORT,RST_Pin)//(GPIO_BOP(GPIOB) = RST_Pin)////GPIOB->BSRR=1<<RST //PBout(RST)=1 //RST IO口输出高电平
#define OLED_RS_Clr() gpio_bit_reset(OLED_PORT,DC_Pin)//(GPIO_BC(GPIOB) = DC_Pin)////GPIOB->BRR=1<<DC //PBout(DC)=0 //DC IO口输出低电平
#define OLED_RS_Set() gpio_bit_set(OLED_PORT,DC_Pin)//(GPIO_BOP(GPIOB) = DC_Pin)////GPIOB->BSRR=1<<DC //PBout(DC)=1 //DC IO口输出高电平
#define OLED_SCLK_Clr() gpio_bit_reset(OLED_PORT,D0_Pin)//(GPIO_BC(GPIOB) = D0_Pin)////GPIOB->BRR=1<<D0 //PBout(D0)=0 //D0 IO口输出低电平
#define OLED_SCLK_Set() gpio_bit_set(OLED_PORT,D0_Pin)//(GPIO_BOP(GPIOB) = D0_Pin)////GPIOB->BSRR=1<<D0 //PBout(D0)=1 //D0 IO口输出高电平
#define OLED_SDIN_Clr() gpio_bit_reset(OLED_PORT,D1_Pin)//(GPIO_BC(GPIOB) = D1_Pin)////GPIOB->BRR=1<<D1 //PBout(D1)=0 //D1 IO口输出低电平
#define OLED_SDIN_Set() gpio_bit_set(OLED_PORT,D1_Pin)//(GPIO_BOP(GPIOB) = D1_Pin)////GPIOB->BSRR=1<<D1 //PBout(D1)=1 //D1 IO口输出高电平
②初始化相应IO口
void OLED_GPIO_Init(void)
{
/* enable the led clock */
rcu_periph_clock_enable(RCU_GPIOB);
/* configure led GPIO port */
gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, RST_Pin|DC_Pin|D0_Pin|D1_Pin);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, RST_Pin);
}
③:模拟SPI通信
void OLED_WR_Byte(uint8_t dat,uint8_t cmd)
{
uint8_t i;
if(cmd) OLED_RS_Set();
else OLED_RS_Clr();
for(i=0;i<8;i++)
{
OLED_SCLK_Clr();
if(dat&0x80) OLED_SDIN_Set();
else OLED_SDIN_Clr();
OLED_SCLK_Set();
dat<<=1;
}
OLED_RS_Set();
}
void WriteCmd(unsigned char cmd)//写命令
{
OLED_WR_Byte(cmd,0);
}
void WriteDat(unsigned char dat)//写数据
{
OLED_WR_Byte(dat,1);
}
④:对OLED驱动进行初始化配置,驱动为SSD1306
void OLED_FILL(unsigned char BMP[]) //写数据比如写0x00为清屏 0xff为满频
{
unsigned char y,x;
unsigned char *p;
p=BMP;
for(y=0;y<8;y++)
{
OLED_WR_Byte(0xb0+y,0);
OLED_WR_Byte(0x01,0);
OLED_WR_Byte(0x10,0);
for(x=0;x<128;x++)
OLED_WR_Byte(*p++,1);
}
}
void OLED_Init(void)
{
//*****************//较自己的OLED库修改的地方
OLED_RST_Clr();
delay_1ms(200);
OLED_RST_Set();
//*****************//
WriteCmd(0xAE); //display off
WriteCmd(0x20); //Set Memory Addressing Mode
WriteCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
WriteCmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7
WriteCmd(0xc8); //Set COM Output Scan Direction
WriteCmd(0x00); //---set low column address
WriteCmd(0x10); //---set high column address
WriteCmd(0x40); //--set start line address
WriteCmd(0x81); //--set contrast control register
WriteCmd(0xff); //亮度调节 0x00~0xff
WriteCmd(0xa1); //--set segment re-map 0 to 127
WriteCmd(0xa6); //--set normal display
WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
WriteCmd(0x3F); //
WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
WriteCmd(0xd3); //-set display offset
WriteCmd(0x00); //-not offset
WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
WriteCmd(0xf0); //--set divide ratio
WriteCmd(0xd9); //--set pre-charge period
WriteCmd(0x22); //
WriteCmd(0xda); //--set com pins hardware configuration
WriteCmd(0x12);
WriteCmd(0xdb); //--set vcomh
WriteCmd(0x20); //0x20,0.77xVcc
WriteCmd(0x8d); //--set DC-DC enable
WriteCmd(0x14); //
WriteCmd(0xaf); //--turn on oled panel
OLED_CLS();
}
void OLED_CLS(void)//清屏
{
unsigned char m,n;
for(m=0;m<8;m++)
{
WriteCmd(0xb0+m); //page0-page1
WriteCmd(0x00); //low column start address
WriteCmd(0x10); //high column start address
for(n=0;n<128;n++)
{
WriteDat(0x00);
}
}
}
void OLED_ON(void)
{
WriteCmd(0X8D); //设置电荷泵
WriteCmd(0X14); //开启电荷泵
WriteCmd(0XAF); //OLED唤醒
}
void OLED_OFF(void)
{
WriteCmd(0X8D); //设置电荷泵
WriteCmd(0X10); //关闭电荷泵
WriteCmd(0XAE); //OLED休眠
}
⑤:调用函数(使用他人的图像函数)
void ShowTest(void)
{
int x0=63,y0=31;
unsigned char i =0,j;
int n=1,r=31,v=1,count=0;
int x[30],y[30];
while(1)
{
ClearScreen();
for(i=0;i<n;i++)
{
x[i]=r*cos(2*3.1415926*i/n)+x0;
y[i]=r*sin(2*3.1415926*i/n)+y0;
}
for(i=0;i<=n-2;i++)
{
for(j=i+1;j<=n-1;j++)
DrawLine(x[i],y[i],x[j],y[j]);
}
n+=v;
if(n==20||n==0)
v=-v;
delay_1ms(50);
UpdateScreen();
if(++count==75)
{
count=0;
return ;
}
}
}
void ShowSnow(void)
{
int a[66],i,num=0;
struct Snow
{
short x;
short y;
short speed;
}snow[100];
srand(1);
for(i=0;i<66;i++)
a[i]=(i-2)*10;
ClearScreen();
while(1)
{
//FrameRateUpdateScreen(60);
if(num!=100)
{
snow[num].speed=1+rand()%4;
i=rand()%66;
snow[num].x=a[i];
snow[num].y=0;
num++;
}
for(i=0;i<num;i++)
{
snow[i].y+=snow[i].speed;
DrawPixel(snow[i].x,snow[i].y+1);
DrawPixel(snow[i].x+1,snow[i].y);
DrawPixel(snow[i].x,snow[i].y);
DrawPixel(snow[i].x-1,snow[i].y);
DrawPixel(snow[i].x,snow[i].y-1);
if(snow[i].y>63)
{
snow[i].y=0;
}
}
delay_1ms(30);
UpdateScreen();
ClearScreen();
}
}
|