专注电子技术学习与研究
当前位置:单片机教程网 >> STM32 >> 浏览文章

STM32F4 Discovery + FreeRTOS + 中文字库 + 12864LCD

作者:c_gao   来源:转自c_gao   点击数:  更新时间:2014年07月05日   【字体:
通过几天时间空余时间研究,将FreeRTOS移植到了STM32 Discovery的板子上,并将以前自己做的中文字库解析和简易电子书阅读的程序移植过来.同时采用了SPI接口的12864 OLED液晶屏.再加上板载的几个LED控制以及板载User Button按钮控制电子书向下翻页. 通过配置USART1连接串口蓝牙模块和我的老本本Thinkpad T40p通信.先上图:


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                  //???????(??)
#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;
        }
       
    }

}
关闭窗口

相关文章