STM32软件模拟SPI驱动LCD12864,问题记录解决方法

所用到的单片机为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++;
	}
}

显示效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值