1、代码结构
我们现在想要操作OLED,通过三条线(SCK、DO、CS)与OLED相连,这里没有DI是因为2440只会向OLED传数据而不用接收数据。
oled.c 发送数据
gpio_spi.c 实现spi引脚的初始化
2、gpio_spi.c的SPI_GPIO_Init
GPF1作为OLED片选引脚,设置为输出;
GPG2作为FLASH片选引脚,设置为输出;
GPG4作为OLED的数据(Data)/命令(Command)选择引脚,设置为输出;
GPG5作为SPI的MISO,设置为输入;
GPG6作为SPI的MOSI,设置为输出;
GPG7作为SPI的时钟CLK,设置为输出;
3、如何发送数据
因为我们的oled是通过芯片内部提供电源的,所以看4.2.2VCC Generated by Internal DC/DC Circuit
而不是 VCC Supplied Externally。
所以看oled芯片手册SPEC UG-2864TMBEG01 .pdf的 P29。
write_i(0xAE); /*display off*/
write_i(0x00); /*set lower column address*/
write_i(0x10); /*set higher column address*/
write_i(0x40); /*set display start line*/
......
所以我们就要去实现write_i函数。
从原理图上看,OLED还有一条OLED_DC引脚:
当该引脚=1时,传输的是数据;当该引脚=1时,传输的是命令(打开/关闭、设置亮度)。
因此需要设置cs和OLED_DC引脚
static void OLED_Set_DC(char val)
{
if (val)
GPGDAT |= (1<<4);
else
GPGDAT &= ~(1<<4);
}
static void OLED_Set_CS(char val)
{
if (val)
GPFDAT |= (1<<1);
else
GPFDAT &= ~(1<<1);
}
static void OLEDWriteCmd(unsigned char cmd)
{
OLED_Set_DC(0); /* command */
OLED_Set_CS(0); /* select OLED */
SPISendByte(cmd);
OLED_Set_CS(1); /* de-select OLED */
OLED_Set_DC(1); /* */
}
static void OLEDWriteDat(unsigned char dat)
{
OLED_Set_DC(1); /* data */
OLED_Set_CS(0); /* select OLED */
SPISendByte(dat);
OLED_Set_CS(1); /* de-select OLED */
OLED_Set_DC(1); /* */
}
然后再实现数据发送 SPISendByte() 函数。
怎么实现数据发送?
static void SPI_Set_CLK(char val)
{
if (val)
GPGDAT |= (1<<7);
else
GPGDAT &= ~(1<<7);
}
static void SPI_Set_DO(char val)
{
if (val)
GPGDAT |= (1<<6);
else
GPGDAT &= ~(1<<6);
}
void SPISendByte(unsigned char val)
{
int i;
for (i = 0; i < 8; i++)
{
SPI_Set_CLK(0); //从oled芯片手册上分析出,先低电平
SPI_Set_DO(val & 0x80); //在上升沿发送数据
SPI_Set_CLK(1); //从oled芯片手册上分析出,然后高电平
val <<= 1;
}
}
4、 OLEDPrint
怎么在OLED上显示想要的字符?
OLED的原理:
OLED长有128个像素,宽有64个像素,每个像素用一位来表示,为1则亮,为0则灭。
每一个字节数据Datax控制每列8个像素,在显存里面存放Data数据。
之后所需的操作就是把数据写到显存里面去,如何写到显存可以拆分成两个问题:
怎么发送地址?
怎么发送数据?
打开oled主控芯片手册:SSD1306-Revision 1.1 P34
三种地址表示模式,我们常用页地址模式:
怎么发出页地址和列地址呢?SSD1306-Revision 1.1 P30
一个字符在OLED上的显示图:
//设置处于页地址模式,虽然默认是这种模式,在初始化的时候设置为页地址模式
static void OLEDSetPageAddrMode(void)
{
OLEDWriteCmd(0x20);
OLEDWriteCmd(0x02);
}
static void OLEDClear(void)
{
int page, col=0;
for(page=0; page<8; page++)
{
OLEDSetPos(page, col);
for(col=0; col<128; i++)
{
OLEDWriteDat(0);
}
}
}
static void OLEDSetPos(int page, int col)
{
OLEDWriteCmd(B0 + page);
OLEDWriteCmd(col & 0xf);
OLEDWriteCmd(0x1 + (col >>4 ));
}
static void OLEDPutChar(int page, int col, char val)
{
int i;
const unsigned char* dots = oled_asc2_8x16[val-''];
OLEDSetPos(page, col);
for(i=0; i<8; i++)
{
OLEDWriteDat(dots[i]);
}
OLEDSetPos(page+1, col);
for(i=0; i<8; i++)
{
OLEDWriteDat(dots[i+8]);
}
}
void OLEDPrint(int page, int col, char *str)
{
while(str[i])
{
OLEDPutChar(page, col, str[i]);
col += 8;
if(col > 127)
{
col = 0;
page += 2;
}
i++;
}
}