FreeRTOS的移植我是基于FreeRTOS最新官方7.5.2版的Demo: CORTEX_M4F_STM32F407ZG-SK 移植的.不过这个Demo里的RCC,PLL,HSE等相关配置不符合STM32 Discovery的实际情况,我重新用ST公司官方提供的system_stm32f4xx.c重新替换实现,同时去掉了Demo里的除LED任务外的所有其它任务,并修改中断等其它配置.重新自己写了几个Task实现自己的要求.
这里提一下,网上流传甚广的12864的SPI驱动是有问题的.主要表现在一个重要的设置坐标的函数,错误版本代码如下:
void LCD_Set_Pos(unsigned char x, unsigned char y)
{
LCD_WrCmd(0xb0+y);
LCD_WrCmd((x&0x0f)|0x01); //0000 1111
LCD_WrCmd(((x&0xf0)>>4)|0x10);//0001 1111
}
使用这个函数明显的错误发生在x的坐标定位会出问题,比如当你使用LCD_Set_Pos(126,0)和LCD_Set_Pos(127,0)时效果是一样的,都定位到(126,0)位置,无法点亮x=127这最后一列的像素.结果通过查看12864控制芯片的硬件文档找到原因:
文档明确表示,x坐标的设置将坐标字节的低4位直接写入,将D4位置1后再将坐标字节的高4位一起写入设置.而上面的代码中:
LCD_WrCmd((x&0x0f)|0x01); //0000 1111
显然画蛇添足,应改为:
LCD_WrCmd(x&0x0f);
即可.
另外, 由于12864的控制芯片内的显存是按位进行素像迭制的,并且写入显存时还得按节字为单位进行.实际程序中非常不方便进行单像素的随意控制.为此,我写了个中间层,这个中间层对每个像素按字节操作,GUI操作都在位于内存中开辟的中间层显存中进行.然后渲染到屏上去时再转换成为控制芯片要求的格式.
代码如下:
[1]. hal_lcd.h
#ifndef HAL_LCD_H
#define HAL_LCD_H
#include
#define LCD_WIDTH 128
#define LCD_HEIGHT 64
#define PIXEL_PER_BYTE 8
#define LOG_PIXEL_PER_BYTE 3
#define USE_LOG_WIDTH_32 5
#define USE_LOG_WIDTH_64 6
#define USE_LOG_WIDTH_128 7
#define USE_LOG_WIDTH_256 8
#define CUR_LOG_WIDTH USE_LOG_WIDTH_128
#define BIT(n) (1<<(n))
extern unsigned char hal_lcd_buff[LCD_WIDTH*LCD_HEIGHT];
extern unsigned char lcd_buff[(LCD_WIDTH*LCD_HEIGHT)>>LOG_PIXEL_PER_BYTE];
extern unsigned long render_count;
inline void set_pixel(int x, int y, unsigned char clr)
{
hal_lcd_buff[(y<<CUR_LOG_WIDTH)+x]=clr;
}
inline unsigned char get_pixel(int x, int y)
{
return hal_lcd_buff[(y<<CUR_LOG_WIDTH)+x];
}
inline void clear_hal_lcd_buff()
{
int num = LCD_WIDTH*LCD_HEIGHT;
for(int i=0; i
hal_lcd_buff[i]=0;
}
inline void clear_lcd_buff()
{
int num = (LCD_WIDTH*LCD_HEIGHT)>>LOG_PIXEL_PER_BYTE;
for(int i=0; i
lcd_buff[i]=0;
}
inline void clear_buff()
{
clear_hal_lcd_buff();
clear_lcd_buff();
}
void DrawCharacter10(unsigned char color);
void GenLcdBuff();
void RenderBuff();
void Render();
#endif
[2]. hal_lcd.c
#include "hal_lcd.h"
#include "LQ12864.h"
#include "gb_10_zhi.h"
#include "5_7font.h"
#include "mylife_txt.h"
unsigned char hal_lcd_buff[LCD_WIDTH*LCD_HEIGHT];
unsigned char lcd_buff[(LCD_WIDTH*LCD_HEIGHT)>>LOG_PIXEL_PER_BYTE];
unsigned long render_count=1;
#define ASC_COUNT 95 //????
#define ASC_START 32 //????
#define ASC_WIDTH 8 //???????(??)
#define ASC_HEIGHT 8 //???????(??)
#define ROW_SPACE 1 //???(??)
#define COL_SPACE 1 //???(??)
#define TAB_SPACE_NUM 4 //??TAB?????????
#define CN_CHAR_HEIGHT 10//??????
#define CN_CHAR_WIDTH 10//??????
void GenLcdBuff()
{
int x,y,k;
unsigned char dist_byte;
int start_y,end_y;
int i;
int ii=0;
for(y=0; y<(LCD_HEIGHT>>LOG_PIXEL_PER_BYTE); y++)
{
for(x=0; x
{
dist_byte = 0;
start_y = (y<<LOG_PIXEL_PER_BYTE);
end_y = start_y + PIXEL_PER_BYTE;
for(i=0,k=start_y; k
{
if(get_pixel(x,k))
dist_byte |= BIT(i);
}
lcd_buff[ii++]=dist_byte;
}
}
}
void RenderBuff()
{
Draw_BMP(0,0,127,7,lcd_buff);
}
void Render()
{
GenLcdBuff();
Draw_BMP(0,0,127,7,lcd_buff);
}
char* file;//file pointer
unsigned int nFilePosition;
unsigned int nOffset;
static void memcpy(void* dst, const void* src, unsigned int count)
{
unsigned char* cdst = (unsigned char*)dst;
unsigned char* csrc = (unsigned char*)src;
int i=0;
while((i++)
*(cdst++) = *(csrc++);
}
int DrawASC(int nRow,int nCol,int nIndex,unsigned char color)
{
if( nIndex == ' ' - ASC_START ) //?????,??,????3,????,?????????,??????
return 3;
int nWidth=0;
if(nIndex > ASC_COUNT || nIndex < 0)
return nWidth;
unsigned char * pLocation=nAsciiDot+nIndex*ASC_WIDTH;
unsigned char * ptemp=NULL;
//int n=0;
int i=0,j=0;
int row=nRow,col=nCol;
//uint16 color=RGB15(31,31,31)|BIT(15);
for(i=0; i
{
ptemp=pLocation+i;
for(j=0; j
{
if( (*ptemp)&BIT(ASC_WIDTH-j-1) )
{
set_pixel(col,row,color);
if( j > nWidth)
nWidth=j;
}
//else //???
// putpixel_FB(row,col,RGB15(31,0,0)|BIT(15),buffer);
col++;
}
col=nCol;
row++;
}
if( nIndex == '!'-ASC_START ||
nIndex == ','-ASC_START ||
nIndex == '.'-ASC_START ||
nIndex == '?'-ASC_START ||
nIndex == '"'-ASC_START ||
nIndex == ';'-ASC_START ||
nIndex == ':'-ASC_START )
return ASC_WIDTH;
else
return nWidth+1;
}
typedef struct tag_Pos
{
int row;
int col;
} Pos;
void DrawCharacter10(unsigned char color)
{
char bDual=0;
unsigned char cnChar[2];
unsigned int nSection;
unsigned int nPosition;
int xx=0;
int yy=0;
file=(char*)(mylife_txt+nFilePosition);
char* pStr=file;
unsigned int nIndex=0;//gb_10_zhi_size;abcdef
cnChar[0]=pStr[nIndex++];
unsigned int nLen=mylife_txt_size;//strlen(pStr);
while(nFilePosition+nIndex < nLen && yy < LCD_HEIGHT-CN_CHAR_HEIGHT)
{
if(cnChar[0] & BIT(7))
{
cnChar[1]=pStr[nIndex++];
bDual=1;
}
else
bDual=0;
if(bDual)
{
nSection=( (cnChar[0]-0xA0) & 0x7f ) -1;
nPosition=(cnChar[1]-0xA0) & 0x7f;
long nOffset=(nSection*94+nPosition)*13;//((9*94)+1)*13+k*13;//
unsigned char font[13];
memcpy(font,gb_10_zhi+nOffset,13);
int i=0;
int j=0;
int x=0,y=0;
for(i=0; i<10; i++)
{
for(j=0; j<8; j++)
{
if(font[i] & BIT(j))
{
x=xx+8-j-1;//(i*8+j);
y=i;//(i*8+j)/12;
set_pixel(x,yy+y,color);
}
}
}
for(i=10; i<13; i++)
{
for(j=0; j<8; j++)
{
if(font[i] & BIT(j))
{
x=xx+8+(2-j%2-1);
y=4*(i-9)-j/2-1;//(i-10)*4+j/2;
set_pixel(x,yy+y,color);
}
}
}
xx+=(CN_CHAR_WIDTH+COL_SPACE);
}
else
{
if(cnChar[0] == 0x0D && nIndex < nLen-1)
{
cnChar[1]=pStr[nIndex++];
if(cnChar[1]== 0x0A)
{
yy+=(CN_CHAR_HEIGHT+ROW_SPACE);
xx=0;
}
}
else
{
switch(cnChar[0])
{
case '\n':
xx=0;
yy+=(CN_CHAR_HEIGHT+ROW_SPACE);
break;
case '\t'://???????,????4???
{
if(xx < LCD_WIDTH)
{
xx=xx+TAB_SPACE_NUM*(CN_CHAR_WIDTH+ROW_SPACE);
if(xx >= LCD_WIDTH)
{
yy+=(CN_CHAR_HEIGHT+ROW_SPACE);
xx=0;
}
}
break;
}
default:
xx+=DrawASC(yy+(CN_CHAR_HEIGHT-ASC_HEIGHT),xx,cnChar[0]-ASC_START,color);
xx+=COL_SPACE;
break;
}//switch
}
}
cnChar[0]=pStr[nIndex++];
nOffset=nIndex-1;
if(xx+CN_CHAR_WIDTH >= LCD_WIDTH)
{
yy+=(CN_CHAR_HEIGHT+ROW_SPACE);
xx=0;
}
}
}