小弟用STM32驱动12864遇到个奇怪的问题,12864由ks0108驱动,将要写的数据写入显示ram中,比如将100写入,读回来正确,但是写入0xFF,再读回来发现不是0xFF,不管是写入100还是0xFF,lcd上都没有任何反应,将复位,忙,显示开关状态都读回来,发现没什么问题。实在找不到问题所在。
因为硬件没有经过调试,所以根本不知道是硬件的问题还是软件的问题,希望搞过的朋友帮忙看看。
硬件图:
代码:
/* Private Includes ----------------------------------------*/
#include "LCD.h"
#include <math.h>
#include <stdio.h>
#include "stm32f10x.h"
/* Private Defines ------------------------------------------*/
/* Private Variables*/
extern const unsigned char Asii0610[];
/* Private Functions ---------------------------------------*/
/*
**************************************************************************************************
*
* Function Name: LCD_WriteData
*
* Author: xiepengcheng Version: 1.0 Date: 2011-05-28
*
* Description: 通过数据口给LCD写数据
*
* Param : unsigned char data : 要写的8位数
*
* Return : None
*
* Notes: 为底层函数,供上层函数调用
*
*
*
**************************************************************************************************
*/
void LCD_WriteData(unsigned char data)
{
// printf("LCD_WriteData--------begin\n\r");
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
LCD_ConfigDataDirection(LCD_DATA_OUT);
GPIO_SetBits(GPIOB, DI);
GPIO_ResetBits(GPIOB, WR);
GPIO_SetBits(GPIOB, E);
GPIO_Write(GPIOA, data);
LCD_DelayUs(800);
GPIO_ResetBits(GPIOB, E);
LCD_DelayUs(800);
GPIO_SetBits(GPIOB, E);
// printf("LCD_WriteData--------end\n\r");
}
/*
**************************************************************************************************
*
* Function Name: LCD_WriteCmd
*
* Author: xiepengcheng Version: 1.0 Date: 2011-05-28
*
* Description: 通过数据口给LCD写命令
*
* Param : unsigned char cmd : 要写的8位命令值
*
* Return : None
*
* Notes: 为底层函数,供上层函数调用
*
*
*
**************************************************************************************************
*/
void LCD_WriteCmd(unsigned char cmd)
{
// printf("LCD_WriteCmd--------begin\n\r");
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
LCD_ConfigDataDirection(LCD_DATA_OUT);
GPIO_ResetBits(GPIOB, DI);
GPIO_ResetBits(GPIOB, WR);
GPIO_SetBits(GPIOB, E);
GPIO_Write(GPIOA, cmd);
LCD_DelayUs(800);
GPIO_ResetBits(GPIOB, E);
LCD_DelayUs(800);
GPIO_SetBits(GPIOB, E);
// printf("LCD_WriteCmd--------end\n\r");
}
/*
**************************************************************************************************
*
* Function Name: LCD_ReadData
*
* Author: xiepengcheng Version: 1.0 Date: 2011-05-28
*
* Description: 通过数据口从LCD读数据
*
* Param : None
*
* Return : unsigned char : 读返回的数据
*
* Notes: 为底层函数,供上层函数调用
*
*
*
**************************************************************************************************
*/
unsigned char LCD_ReadData(void)
{
unsigned char data = 0;
printf("LCD_ReadData--------begin\n\r");
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
LCD_ConfigDataDirection(LCD_DATA_IN);
GPIO_SetBits(GPIOB, DI);
GPIO_SetBits(GPIOB, WR);
//空读操作
GPIO_SetBits(GPIOB, E);
LCD_DelayUs(800);
GPIO_ResetBits(GPIOB, E);
LCD_DelayUs(800);
GPIO_SetBits(GPIOB, E);
data = GPIO_ReadInputData(GPIOA);
LCD_DelayUs(800);
GPIO_ResetBits(GPIOB, E);
LCD_DelayUs(800);
GPIO_SetBits(GPIOB, E);
printf("LCD_ReadData--------end\n\r");
printf("ReadData = %d--------begin\n\r", data);
return data;
}
/*
**************************************************************************************************
*
* Function Name: LCD_Open
*
* Author: xiepengcheng Version: 1.0 Date: 2011-05-28
*
* Description: 打开LCD,实际为写入显示开指令
*
* Param : None
*
* Return : None
*
* Notes:
*
*
*
**************************************************************************************************
*/
void LCD_Open(void)
{
printf("LCD_Open--------begin\n\r");
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
LCD_WriteCmd(0x3F);
printf("LCD_Open--------end\n\r");
}
/*
**************************************************************************************************
*
* Function Name: LCD_Close
*
* Author: xiepengcheng Version: 1.0 Date: 2011-05-28
*
* Description: 关闭LCD显示,实际为写入显示关指令
*
* Param : None
*
* Return : None
*
* Notes:
*
*
*
**************************************************************************************************
*/
void LCD_Close(void)
{
printf("LCD_Close--------begin\n\r");
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
LCD_WriteCmd(0x3E);
printf("LCD_Close--------end\n\r");
}
void LCD_Delay(int count)
{
for(; count > 0; count--);
}
LCD_FlagStatus LCD_GetStatus(LCD_Status LCD_FLAG)
{
unsigned char data;
LCD_FlagStatus status = LCD_RESET;
// printf("LCD_GetStatus--------begin\n\r");
LCD_ConfigDataDirection(LCD_DATA_IN);
GPIO_SetBits(GPIOB, WR);
GPIO_ResetBits(GPIOB, DI);
//空读操作
GPIO_SetBits(GPIOB, E);
//需要延时一下
LCD_DelayUs(800);
GPIO_ResetBits(GPIOB, E);
GPIO_SetBits(GPIOB, E);
//需要延时一下
LCD_DelayUs(800);
GPIO_ResetBits(GPIOB, E);
LCD_DelayUs(800);
GPIO_SetBits(GPIOB, E);
data = GPIO_ReadInputData(GPIOA);
if(data & LCD_FLAG)
{
status = LCD_SET;
}
else
{
status = LCD_RESET;
// printf("GetStatus = %d\n\r", status);
}
// printf("LCD_GetStatus--------end\n\r");
return status;
}
void LCD_SelectPage(unsigned char page)
{
// printf("LCD_SelectPage--------begin\n\r");
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
LCD_WriteCmd(0xB8 + page);
// printf("LCD_SelectPage--------end\n\r");
}
void LCD_SelectYAddr(unsigned char yAddr)
{
// printf("LCD_SelectYAddr--------begin\n\r");
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
LCD_WriteCmd(0x40 + yAddr);
// printf("LCD_SelectYAddr--------end\n\r");
}
void LCD_SelectStartRow(unsigned char startRow)
{
// printf("LCD_SelectStartRow--------begin\n\r");
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
LCD_WriteCmd(0xC0 + startRow);
// printf("LCD_SelectStartRow--------end\n\r");
}
/*
**************************************************************************************************
*
* Function Name: LCD_Clear
*
* Author: xiepengcheng Version: 1.0 Date: 2011-05-28
*
* Description: 清除整个LCD。
*
* Param : None
*
* Return : None
*
* Notes:
*
*
*
**************************************************************************************************
*/
void LCD_Clear(void)
{
char i = 0, j = 0;
printf("LCD_Clear--------begin\n\r");
GPIO_SetBits(GPIOB, CS1);
for (i = 0; i < LCD_PAGE_END; i++)
{
LCD_SelectPage(i);
LCD_SelectYAddr(0);
for (j = 0; j < LCD_Y_ADDR_END; j++)
{
LCD_WriteData(0);//列地址自动增1
}
}
GPIO_SetBits(GPIOB, CS2);
for (i = 0; i < LCD_PAGE_END; i++)
{
LCD_SelectPage(i);
LCD_SelectYAddr(0);
for (j = 0; j < LCD_Y_ADDR_END; j++)
{
LCD_WriteData(0);//列地址自动增1
}
}
printf("LCD_Clear--------end\n\r");
}
/*
**************************************************************************************************
*
* Function Name: LCD_DispPoint
*
* Author: xiepengcheng Version: 1.0 Date: 2011-05-28
*
* Description: 显示LCD上指定的点。
*
* Param : unsigned char x:显示点的行地址,0到63
* unsigned char y:显示点的列地址,0到127
*
* Return : None
*
* Notes:
*
*
*
**************************************************************************************************
*/
void LCD_DrawPoint(unsigned char x, unsigned char y)
{
unsigned char page = 0;
unsigned char data = 0;
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
printf("LCD_DrawPoint--------begin\n\r");
page = x / 8;
LCD_SelectPage(page);
LCD_SelectYAddr(y);
data = LCD_ReadData();
data = data | (1 << (x % 8));
// data = 0xFF;
LCD_WriteData(data);
printf("LCD_DrawPoint--------end\n\r");
}
/*
**************************************************************************************************
*
* Function Name: LCD_ClearPoint
*
* Author: xiepengcheng Version: 1.0 Date: 2011-05-28
*
* Description: 清除LCD上指定的点。
*
* Param : unsigned char x:显示点的行地址,0到63
* unsigned char y:显示点的列地址,0到127
*
* Return : None
*
* Notes:
*
*
*
**************************************************************************************************
*/
void LCD_ClearPoint(unsigned char x, unsigned char y)
{
unsigned char page = 0;
unsigned char data = 0;
printf("LCD_ClearPoint--------begin\n\r");
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
page = x / 8;
LCD_SelectPage(page);
LCD_SelectYAddr(y);
data = LCD_ReadData();
data = data & (~(1 << (x % 8)));
LCD_WriteData(data);
printf("LCD_ClearPoint--------end\n\r");
}
/*
**************************************************************************************************
*
* Function Name: LCD_Configuration
*
* Author: xiepengcheng Version: 1.0 Date: 2011-05-28
*
* Description: 配置LCD的时钟,以及命令IO脚。
*
* Param : None
*
* Return : None
*
* Notes: 因为STM32的GPIO口不是双向口,需要配置为输入或者输出,所以数据口的IO根据需要单独配置
*
*
*
**************************************************************************************************
*/
void LCD_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
printf("LCD_Configuration--------begin\n\r");
//配置LCD的命令管脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//配置LCD的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA, ENABLE);
printf("LCD_Configuration--------end\n\r");
}
/*
**************************************************************************************************
*
* Function Name: LCD_ConfigDataDirection
*
* Author: xiepengcheng Version: 1.0 Date: 2011-05-28
*
* Description: 配置数据口的方向。
*
* Param : None
*
* Return : None
*
* Notes: 因为STM32的GPIO口不是双向口,需要配置为输入或者输出,所以数据口的IO根据需要单独配置
*
*
*
**************************************************************************************************
*/
void LCD_ConfigDataDirection(LCD_DataDirection direction)
{
GPIO_InitTypeDef GPIO_InitStructure;
// printf("LCD_ConfigDataDirection--------begin\n\r");
GPIO_InitStructure.GPIO_Mode = (direction ? GPIO_Mode_Out_PP : GPIO_Mode_IN_FLOATING);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4
| GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// printf("LCD_ConfigDataDirection--------end\n\r");
}
/*
**************************************************************************************************
*
* Function Name: LCD_DispCharAt
*
* Author: xiepengcheng Version: 1.0 Date: 2011-05-28
*
* Description: 在指定起始地址出显示一个字符。
*
* Param : unsigned char x :起始地址行号
* unsigned char y : 起始地址列号
* unsigned char character:待显示字符(ascii码,能否显示数字,待检测)
*
* Return : None
*
* Notes: 字模文件存在Asii0610文件中,每个字模占10个字节,暂时不支持中文显示,
* 字模文件是否正确有待检测,可用的字模文件还有chinese.c(显示万年历需要的几个中文)
* 和ascii.c(显示数字)
*
*
**************************************************************************************************
*/
void LCD_DispCharAt(unsigned char x, unsigned char y, unsigned char character)
{
//获取该字符在字模中的位置,每个字模有10个字节
unsigned char *pChar = (unsigned char *)Asii0610 + (character - 32) * 10;
unsigned char page = x / 8;
unsigned char i ;
// printf("LCD_DispCharAt--------begin\n\r");
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
LCD_SelectPage(page);
LCD_SelectYAddr(y);
for (i = 0; i < 10; i++)
{
LCD_WriteData(*(pChar + i));
}
// printf("LCD_DispCharAt--------end\n\r");
}
/*
**************************************************************************************************
*
* Function Name: LCD_DispStringAt
*
* Author: xiepengcheng Version: 1.0 Date: 2011-05-28
*
* Description: 在指定起始地址出显示一个字符。
*
* Param : unsigned char x :起始地址行号
* unsigned char y : 起始地址列号
* unsigned char *pString:指向待显示字符串
* unsigned char length : 字符串长度
*
* Return : None
*
* Notes: 字模文件存在Asii0610文件中,每个字模占10个字节,暂时不支持中文显示,
* 字模文件是否正确有待检测,可用的字模文件还有chinese.c(显示万年历需要的几个中文)
* 和ascii.c(显示数字)
* 此函数可能有待改进,可以将length参数去掉,因为字符串以'/0'结束
*
*
**************************************************************************************************
*/
void LCD_DispStringAt(unsigned char x, unsigned char y, unsigned char *pString)
{
printf("LCD_DispStringAt--------begin\n\r");
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
while ( (*pString) != '\0')
{
LCD_DispCharAt(x, y, *pString);
}
printf("LCD_DispStringAt--------end\n\r");
}
void LCD_DrawLine(unsigned char startX, unsigned char startY, unsigned char endX, unsigned char endY)
{
//采用bresenham算法
char dX = 0, dY = 0, incX = 0, incY = 0, temp = 0, flag = 0, judge = 0;
char i = 0;
dX = endX - startX;
dY = endY - startY;
printf("LCD_DrawLine--------begin\n\r");
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
if (dX > 0)
{
incX = 1;
}
else
incX = -1;
if (dY > 0)
{
incY = 1;
}
else
incY = -1;
dX = abs(dX);
dY = abs(dY);
if (dY > dX)
{
temp = dY;
dY = dX;
dX = temp;
//x 和 y翻转
flag = 1;
}
else
flag = 0;
judge = 2 * dY - dX;
for( i = 0; i < dX; i++)
{
LCD_DrawPoint(startX, startY);
if (judge > 0)
{
if (flag == 0)
startY = startY + incY;
else
startX = startX + incX;
judge = judge - 2 * dX;
}
if (flag == 0)
{
startX = startX + incX;
}
else
startY = startY + incY;
judge = judge + 2 * dY;
}
printf("LCD_DrawLine--------end\n\r");
}
void LCD_DispNumAt(unsigned char x, unsigned char y, int data)
{
unsigned char s[64] = {0};
printf("LCD_DispNumAt--------begin\n\r");
while(LCD_GetStatus(LCD_BUSY_FLAG) != RESET);
sprintf((char *)s, "%s", (char *)data);
LCD_DispStringAt(x, y, s);
printf("LCD_DispNumAt--------end\n\r");
}
//void LCD_Init(void)
//{
// LCD_Close();
// LCD_DelayUs(400);
//
//}
void LCD_DelayUs(unsigned long n)
{
unsigned long j;
while(n--)
{
j=8;
while(j--);
}
}
void LCD_DelayMs(unsigned long n)
{
while(n--)
LCD_DelayUs(1100);
}
void LCD_DrawTest(void);
void LCD_Test(void);
/* Private functions ---------------------------------------------------------*/
int main(void)
{
int i;
LCD_FlagStatus status;
unsigned char data = 0;
SystemInit();
RCC_Config();
USART_Config();
LCD_Configuration();
GPIO_SetBits(GPIOB, CS1);
GPIO_ResetBits(GPIOB, CS2);
LCD_Close();
LCD_Open();
GPIO_SetBits(GPIOB, CS2);
GPIO_ResetBits(GPIOB, CS1);
LCD_Close();
LCD_Open();
LCD_WriteData(10);
data = LCD_ReadData();
printf("data = %d \n\r", data);
status = LCD_GetStatus(LCD_ON_OFF_FLAG);
printf("ON_OFF_STATUS = %d \n\r", status);
status = LCD_GetStatus(LCD_RESET_FLAG);
printf("RESET_STATUS = %d \n\r", status);
status = LCD_GetStatus(LCD_BUSY_FLAG);
printf("BUSY_STATUS = %d \n\r", status);
LCD_Test();
while(1)
{
for(i = 3000000; i > 0; i--);
printf("in main\n\r");
}
}
void LCD_Test(void)
{
char i = 0, j = 0;
unsigned char data = 0;
printf("LCD_Test--------begin\n\r");
GPIO_SetBits(GPIOB, CS1);
GPIO_ResetBits(GPIOB, CS2);
for (i = 0; i < LCD_PAGE_END; i++)
{
LCD_WriteCmd(0xc0);
LCD_SelectPage(i);
LCD_SelectYAddr(0);
for (j = 0; j < LCD_Y_ADDR_END; j++)
{
LCD_WriteData(220);//列地址自动增1
data = LCD_ReadData();
printf("read_data = %d \n\r", data);
}
}
GPIO_ResetBits(GPIOB, CS1);
GPIO_SetBits(GPIOB, CS2);
for (i = 0; i < LCD_PAGE_END; i++)
{
LCD_SelectPage(i);
LCD_SelectYAddr(0);
for (j = 0; j < LCD_Y_ADDR_END; j++)
{
LCD_WriteData(220);//列地址自动增1
data = LCD_ReadData();
printf("read_data = %d \n\r", data);
}
}
printf("LCD_Test--------end\n\r");
}
此外,由于疏忽,没有将数据口上拉,所以在每次读写数据的时候,都重新配置数据口,读时配置为浮动输入,写数据的时候配置为推挽输出。并且LCD的rst脚悬空。 |
|