所用到的单片机为STM32F103RE
一:所遇到的问题
1、LCD12864接口识别错误,接口错误的识别为IIC,真实接口为SPI,只不过没有MISO引脚,导致硬件接线时直接接到了单片机的IIC,造成驱动调试时各种不成功
2、采用软件模拟SPI的方式驱动,网上找了个例程,拿来后无法调通,采用示波器抓取SCL和SDA两个引脚波形,发现一直显示低电平;检查硬件连接正常;对这两个接口采用置位指令GPIO_SetBits(),示波器抓取波形,发现仍旧显示低电平,无法置位;接口配置如下:
void SPI_Init(void)
{
/*定义一个GPIO_InitTypeDef类型的(基本IO)结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/***** 使能 GPIO 时钟 *****/
/* 使能 FLASH_SPI引脚的GPIO时钟 */
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
/* < 配置 SPI 引脚: SDA,SCL;配置LCD屏RST接口 > */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
/* 设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* 调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO_B*/
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* < 配置 SPI引脚: CS;配置屏RS(A0)接口 > */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
3、调整代码后,示波器抓取SCL和SDA波形,有数据输出,但是LCD仍无法显示,代码如下
#include "lcd_12864.h"
#include "ziku.h"
/*******************************************************************************
//函数名: Lcdwritecom
//功能:lcd写指令
//输入:com指令
//输出:无
********************************************************************************/
//SPI四种模式:极性(CPOL)-相位(CPHA)
void LcdWriteCom(uint8_t com)
{
uint8_t cnt;
LCD_CS_RESET;
delay(1);
for(cnt=0;cnt<8;cnt++)
{
if(com &0x80)
{
LCD_SDA_SET;
}
else
{
LCD_SDA_RESET;
}
com <<= 1;
LCD_SCL_SET;//拉高CLK 模式00
LCD_SCL_RESET;//拉低CLK
}
delay(1);
LCD_CS_SET;//释放LCD
}
/*******************************************************************************
//函数名:Lcdwritedata
//功能:lcd写数据
//输入:dat数据
//输出:无
********************************************************************************/
void LcdWriteData(uint8_t dat)
{
uint8_t cnt;
LCD_CS_RESET;
delay(1);
for(cnt=0;cnt<8;cnt++)
{
if(dat &0x80)
{
LCD_SDA_SET;
}
else
{
LCD_SDA_RESET;
}
dat <<= 1;
LCD_SCL_SET;//拉高CLK 模式00
LCD_SCL_RESET;//拉低CLK
}
delay(1);
LCD_CS_SET;//释放LCD
}
/*LCD模块初始化*/
void LCD_Init()
{
LCD_RST_RESET; /*低电平复位*/
delay(50);
LCD_RST_SET; /*复位完毕*/
delay(1);
LcdWriteCom(0xe2); /*软复位*/
delay(1);
LcdWriteCom(0xa0); /*列扫描顺序:从左到右*/
LcdWriteCom(0xc8); /*行扫描顺序:从下到上,c0从上到下*/
LcdWriteCom(0xa2); /*设置偏压比1/9*/
LcdWriteCom(0x2f); /*控制电源*/
LcdWriteCom(0x25); /*粗调对比度*/
LcdWriteCom(0x81); /*微调对比度,进入微调对比度命令*/
LcdWriteCom(0x10); /*设置电压的参数RR值*/
LcdWriteCom(0x40); /*起始行:第一行开始*/
LcdWriteCom(0xaf); /*开显示*/
}
void Lcd_Address(uint16_t page,uint16_t column)
{
column=column-0x01;
LcdWriteCom(0xb0+page-1); /*设置页地址*/ //1-8
LcdWriteCom(0x10+(column>>4&0x0f)); /*设置列地址的高4位*///0-128
LcdWriteCom(column&0x0f); /*设置列地址的低4位*/
}
/*全屏清屏*/
void ClearScreen()
{
unsigned char i,j;
for(i=0;i<9;i++)
{
LcdWriteCom(0xb0+i); //从第0页开始
LcdWriteCom(0x10);
LcdWriteCom(0x00);
for(j=0;j<132;j++)
{
LcdWriteData(0x00);
}
}
}
/*显示128x64点阵图像*/
void Display_128x64(uint8_t *dp)
{
uint8_t i,j;
for(j=0;j<8;j++)
{
Lcd_Address(j+1,1);
for (i=0;i<128;i++)
{
LcdWriteData(*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/
dp++;
}
}
}
/*显示16x16点阵图像、汉字、生僻字或16x16点阵的其他图标*/
void Display_Graphic_16x16(uint8_t page,uint8_t column,uint8_t *dp)
{
uint8_t i,j;
for(j=0;j<2;j++)
{
Lcd_Address(page+j,column);
for (i=0;i<16;i++)
{
LcdWriteData(*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/
dp++;
}
}
}
/*显示8x16点阵图像、ASCII, 或8x16点阵的自造字符、其他图标*/
void Display_Graphic_8x16(uint8_t page,uint8_t column,uint8_t *dp)
{
uint8_t i,j;
for(j=0;j<2;j++)
{
Lcd_Address(page+j,column);
for (i=0;i<8;i++)
{
LcdWriteData(*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/
dp++;
}
}
}
/*显示5*8点阵图像、ASCII, 或5x8点阵的自造字符、其他图标*/
void Display_Graphic_5x8(uint8_t page,uint8_t column,uint8_t *dp)
{
uint8_t col_cnt;
Lcd_Address(page,column);
for (col_cnt=0;col_cnt<5;col_cnt++)
{
LcdWriteData(*dp);
dp++;
}
}
二:问题解决
问题1:采用软件模拟SPI的方式解决
问题2:在对SCL、SDA引脚配置时,引脚模式需要更改为正常推挽输出,不需要用复用推挽输出,问题解决
/* < 配置 SPI 引脚: SDA,SCL;配置LCD屏RST接口 > */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
问题3:LCD无法显示,期间试过spi的四种模式,均不能显示,查询代码,发现lcd的A0引脚,即发送指令/数据引脚未使用到代码中,将此引脚加到代码中运行测试,屏幕实现正常显示,代码如下:
#include "lcd_12864.h"
#include "ziku.h"
/*******************************************************************************
//函数名: Lcdwritecom
//功能:lcd写指令
//输入:com指令
//输出:无
********************************************************************************/
//SPI四种模式:极性(CPOL)-相位(CPHA)
void LcdWriteCom(uint8_t com)
{
uint8_t cnt;
LCD_CS_RESET;
LCD_RS_RESET;
delay(1);
for(cnt=0;cnt<8;cnt++)
{
if(com &0x80)
{
LCD_SDA_SET;
}
else
{
LCD_SDA_RESET;
}
com <<= 1;
// LCD_SCL_RESET;//拉低CLK 模式10
// LCD_SCL_SET;//拉高CLK
LCD_SCL_SET;//拉高CLK 模式00
LCD_SCL_RESET;//拉低CLK
}
delay(1);
LCD_CS_SET;
}
/*******************************************************************************
//函数名:Lcdwritedata
//功能:lcd写数据
//输入:dat数据
//输出:无
********************************************************************************/
void LcdWriteData(uint8_t dat)
{
uint8_t cnt;
LCD_CS_RESET;
LCD_RS_SET;
delay(1);
for(cnt=0;cnt<8;cnt++)
{
if(dat &0x80)
{
LCD_SDA_SET;
}
else
{
LCD_SDA_RESET;
}
dat <<= 1;
// LCD_SCL_RESET;//拉低CLK 模式10
// LCD_SCL_SET;//拉高CLK
LCD_SCL_SET;//拉高CLK 模式00
LCD_SCL_RESET;//拉低CLK
}
delay(1);
LCD_CS_SET;
}
/*LCD模块初始化*/
void LCD_Init()
{
LCD_RST_RESET; /*低电平复位*/
delay(50);
LCD_RST_SET; /*复位完毕*/
delay(1);
LcdWriteCom(0xe2); /*软复位*/
delay(1);
LcdWriteCom(0xa0); /*列扫描顺序:从左到右*/
LcdWriteCom(0xc8); /*行扫描顺序:从下到上,c0从上到下*/
LcdWriteCom(0xa2); /*设置偏压比1/9*/
LcdWriteCom(0x2f); /*控制电源*/
LcdWriteCom(0x25); /*粗调对比度*/
LcdWriteCom(0x81); /*微调对比度,进入微调对比度命令*/
LcdWriteCom(0x10); /*设置电压的参数RR值*/
LcdWriteCom(0x40); /*起始行:第一行开始*/
LcdWriteCom(0xaf); /*开显示*/
}
void Lcd_Address(uint16_t page,uint16_t column)
{
column=column-0x01;
LcdWriteCom(0xb0+page-1); /*设置页地址*/ //1-8
LcdWriteCom(0x10+(column>>4&0x0f)); /*设置列地址的高4位*///0-128
LcdWriteCom(column&0x0f); /*设置列地址的低4位*/
}
/*全屏清屏*/
void ClearScreen()
{
unsigned char i,j;
for(i=0;i<9;i++)
{
LcdWriteCom(0xb0+i); //从第0页开始
LcdWriteCom(0x10);
LcdWriteCom(0x00);
for(j=0;j<132;j++)
{
LcdWriteData(0x00);
}
}
}
/*显示128x64点阵图像*/
void Display_128x64(uint8_t *dp)
{
uint8_t i,j;
for(j=0;j<8;j++)
{
Lcd_Address(j+1,1);
for (i=0;i<128;i++)
{
LcdWriteData(*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/
dp++;
}
}
}
/*显示16x16点阵图像、汉字、生僻字或16x16点阵的其他图标*/
void Display_Graphic_16x16(uint8_t page,uint8_t column,uint8_t *dp)
{
uint8_t i,j;
for(j=0;j<2;j++)
{
Lcd_Address(page+j,column);
for (i=0;i<16;i++)
{
LcdWriteData(*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/
dp++;
}
}
}
/*显示8x16点阵图像、ASCII, 或8x16点阵的自造字符、其他图标*/
void Display_Graphic_8x16(uint8_t page,uint8_t column,uint8_t *dp)
{
uint8_t i,j;
for(j=0;j<2;j++)
{
Lcd_Address(page+j,column);
for (i=0;i<8;i++)
{
LcdWriteData(*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/
dp++;
}
}
}
/*显示5*8点阵图像、ASCII, 或5x8点阵的自造字符、其他图标*/
void Display_Graphic_5x8(uint8_t page,uint8_t column,uint8_t *dp)
{
uint8_t col_cnt;
Lcd_Address(page,column);
for (col_cnt=0;col_cnt<5;col_cnt++)
{
LcdWriteData(*dp);
dp++;
}
}
显示效果: