您的位置:首页 > 其它

SPI--SPI协议和OLED裸板程序

2017-09-22 17:20 459 查看
关于SPI协议:

http://www.wangdali.net/spi/

http://blog.csdn.net/ce123_zhouwei/article/details/6878547

——————————————————————–

sck 时钟 Do 输出 Di 输入 cs0 cs1 片选信号

一个传输协议:

cs0低电平选通,sck的一个上升沿读取Do引脚,D0此时为低电平,即最高位的0被发出。

oled.c 负责组织哪些数据

gpio_spi.c 负责写入数据到oled

在主函数中实现这三个函数:

(1)SPIInit();

(2)OLEDInit();

(3)OLEDPrint(0,0,”hello xs”);

————————————————————————

(1)SPIInit()的实现: 查看gpio_spi.c





void SPIInit(void)
{
/*初始化引脚*/
SPI_GPIO_Init();
}

Jump to definition    SPI_GPIO_Init

static void SPI_GPIO_Init(void)
{
/* GPF1 OLED_CSn output 具体的配置可以查看spi_jz244原理图 */
GPFCON &= ~(3<<(1*2)); //  GPFCON清零,1*2表示GPF1的两位,3理解为11然后取反
GPFCON |= (1<<(1*2));// 1理解为01,表示为输出
GPFDAT |= (1<<1);//01左移一位变为10,GPF1配置为输出时候,写1高电平,写0低电平。

/* GPG2 FLASH_CSn output
* GPG4 OLED_DC   output
* GPG5 SPIMISO   input
* GPG6 SPIMOSI   output
* GPG7 SPICLK    output
*/
GPGCON &= ~((3<<(2*2)) | (3<<(4*2)) | (3<<(5*2)) | (3<<(6*2)) | (3<<(7*2)));//2,4,5,6,7表示gpfx
GPGCON |= ((1<<(2*2)) | (1<<(4*2)) | (1<<(6*2)) | (1<<(7*2)));//GPG5为input,不需要配置了
GPGDAT |= (1<<2);
}


(2) OLEDInit()的实现:查看Oled.c

查看SPEC UG-2864TMBEG01手册



参考修改:

void OLEDInit(void)
{
/* 向OLED发命令以初始化 */
OLEDWriteCmd(0xAE); /*display off*/
OLEDWriteCmd(0x00); /*set lower column address*/
...

OLEDSetPageAddrMode();

OLEDClear();//清屏

OLEDWriteCmd(0xAF); /*display ON*/
}


OLEDWriteCmd的实现 :

cs片选信号拉低,sck有脉冲信号,根据DC信号的高低判断Do发送的是数据还是命令

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); /*  */
}


关于:OLED_Set_DC 、 OLED_Set_CS 、 SPISendByte(dat)的实现

/* GPG4 OLED_DC   output*/
/* GPF1 OLED_CSn output */

static void OLED_Set_DC(char val)
{
if (val)
GPFDAT |= (1<<3);//理解为第三位置1
else
GPFDAT &= ~(1<<3);
}

static void OLED_Set_CS(char val)
{
if (val)
GPGDAT |= (1<<1);//理解为第一位置1
else
GPGDAT &= ~(1<<1);
}

//参考:传输协议

void SPISendByte(unsigned char val)
{
int i;
for (i = 0; i < 8; i++)
{
SPI_Set_CLK(0);//拉低
SPI_Set_DO(val & 0x80);//从最高位开始发数据
SPI_Set_CLK(1);//拉高
val <<= 1;
}
}


SPISendByte函数中 SPI_Set_CLK 、SPI_Set_DO的实现

SPI_Set_CLK

/*GPG7 SPICLK  output*/

static void SPI_Set_CLK(char val)
{
if (val)
GPGDAT |= (1<<7);
else
GPGDAT &= ~(1<<7);
}


SPI_Set_DO

/* GPG6 SPIMOSI  output*/

static void SPI_Set_DO(char val)
{
if (val)
GPGDAT |= (1<<6);
else
GPGDAT &= ~(1<<6);
}


————————————————————————

(3)OLEDPrint(int page, int col, char *str)的实现

打开SSD1306-Revision 1.1 (Charge Pump)



页地址模式 64行分为8页,每页对应8行; 列地址分两次发送,先发送底字节,再发送高字节。

/* page: 0-7
* col : 0-127
* 字符: 8x16象素
*/
void OLEDPrit (int page ,int col,char *str)
{
int i;
while(str[i])
{
OLEDPutChar(page,col,str[i]);
col +=8;
if(col >127)
{
col=0;
page=2;
}
i++;
}
}


关于字模的函数可以从stm32(战舰STM32\实验12 OLED显示实验\HARDWARE\OLED)的函数oledfont.h中截取,就是这里用到的

8X16的字模。

void OLEDPutChar(int page, int col, char c)
{
int i = 0;
/* 得到字模 */
const unsigned char *dots = oled_asc2_8x16[c - ' '];

/* 发给OLED */
OLEDSetPos(page, col);
/* 发出8字节数据 */
for (i = 0; i < 8; i++)
OLEDWriteDat(dots[i]);

OLEDSetPos(page+1, col);
/* 发出8字节数据 */
for (i = 0; i < 8; i++)
OLEDWriteDat(dots[i+8]);

}


OLEDSetPos(int page,int col) 函数的实现:





static void OLEDSetPos(int page, int col)//设置页地址,列地址
{
OLEDWriteCmd(0xB0 + page); /* page address  0011*/

OLEDWriteCmd(col & 0xf);   /* Lower Column Start Address 0012*/
OLEDWriteCmd(0x10 + (col >> 4));   /* Lower Higher Start Address */
}


OLEDSetPageAddrMode(), OLEDClear()函数的实现:



void OLEDInit(void){
...
OLEDSetPageAddrMode();
OLEDClear();
...
}

static void OLEDSetPageAddrMode(void)
{
OLEDWriteCmd(0x20);//设置存储地址模式
OLEDWriteCmd(0x02);//页地址模式
}

//清屏函数:

static void OLEDClear(void)
{
int page, i;
for (page = 0; page < 8; page ++)
{
OLEDSetPos(page, 0);//第0列开始
for (i = 0; i < 128; i++)
OLEDWriteDat(0);
}
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: