專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> STM32 >> 瀏覽文章

STM32F4 Discovery + FreeRTOS + 中文字庫(kù) + 12864LCD

作者:c_gao   來(lái)源:轉(zhuǎn)自c_gao   點(diǎn)擊數(shù):  更新時(shí)間:2014年07月05日   【字體:
通過(guò)幾天時(shí)間空余時(shí)間研究,將FreeRTOS移植到了STM32 Discovery的板子上,并將以前自己做的中文字庫(kù)解析和簡(jiǎn)易電子書(shū)閱讀的程序移植過(guò)來(lái).同時(shí)采用了SPI接口的12864 OLED液晶屏.再加上板載的幾個(gè)LED控制以及板載User Button按鈕控制電子書(shū)向下翻頁(yè). 通過(guò)配置USART1連接串口藍(lán)牙模塊和我的老本本Thinkpad T40p通信.先上圖:


FreeRTOS的移植我是基于FreeRTOS最新官方7.5.2版的Demo: CORTEX_M4F_STM32F407ZG-SK 移植的.不過(guò)這個(gè)Demo里的RCC,PLL,HSE等相關(guān)配置不符合STM32 Discovery的實(shí)際情況,我重新用ST公司官方提供的system_stm32f4xx.c重新替換實(shí)現(xiàn),同時(shí)去掉了Demo里的除LED任務(wù)外的所有其它任務(wù),并修改中斷等其它配置.重新自己寫(xiě)了幾個(gè)Task實(shí)現(xiàn)自己的要求.

這里提一下,網(wǎng)上流傳甚廣的12864的SPI驅(qū)動(dòng)是有問(wèn)題的.主要表現(xiàn)在一個(gè)重要的設(shè)置坐標(biāo)的函數(shù),錯(cuò)誤版本代碼如下:

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
}
使用這個(gè)函數(shù)明顯的錯(cuò)誤發(fā)生在x的坐標(biāo)定位會(huì)出問(wèn)題,比如當(dāng)你使用LCD_Set_Pos(126,0)和LCD_Set_Pos(127,0)時(shí)效果是一樣的,都定位到(126,0)位置,無(wú)法點(diǎn)亮x=127這最后一列的像素.結(jié)果通過(guò)查看12864控制芯片的硬件文檔找到原因:


文檔明確表示,x坐標(biāo)的設(shè)置將坐標(biāo)字節(jié)的低4位直接寫(xiě)入,將D4位置1后再將坐標(biāo)字節(jié)的高4位一起寫(xiě)入設(shè)置.而上面的代碼中:
LCD_WrCmd((x&0x0f)|0x01);       //0000 1111
顯然畫(huà)蛇添足,應(yīng)改為:
LCD_WrCmd(x&0x0f);
即可.

另外, 由于12864的控制芯片內(nèi)的顯存是按位進(jìn)行素像迭制的,并且寫(xiě)入顯存時(shí)還得按節(jié)字為單位進(jìn)行.實(shí)際程序中非常不方便進(jìn)行單像素的隨意控制.為此,我寫(xiě)了個(gè)中間層,這個(gè)中間層對(duì)每個(gè)像素按字節(jié)操作,GUI操作都在位于內(nèi)存中開(kāi)辟的中間層顯存中進(jìn)行.然后渲染到屏上去時(shí)再轉(zhuǎn)換成為控制芯片要求的格式.

代碼如下:
[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                  //???????(??)
#define ASC_HEIGHT                  //???????(??)
#define ROW_SPACE                  //???(??)
#define COL_SPACE                  //???(??)
#define TAB_SPACE_NUM          //??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;
        }
       
    }

}
關(guān)閉窗口

相關(guān)文章