背景
- oled屏移植stemwin,有两种方式,通过自定义打点方式进行移植,或使用stemwin自带驱动库函数移植。
- 使用自带驱动库移植过程中,发现stemwin在emwin基础上进行了"缩水"。
- emwin支持oled屏的GUIDRV_Spage驱动移植,但最新的stemwin544版本并不支持GUIDRV_Spage驱动,只能采用自定义打点方式移植。
显示过程
- 通过显存的方式进行显示:
打点函数定义显存,打点、读点函数;
stemwin负责更改显存内存;
spi负责将显存内存送至oled进行显示;
移植简述
- 打点函数:
定义显存,unsigned char disbuff[8][128],共128*64个点;
写自定义打点、读点函数; - stemwin移植(仅要点):
stm32移植stemwin(自定义打点方式); - spi(略):
stm32与oled屏使用spi通信,刷新时间点送显存内容到oled;
打点函数
oled.c
uint8_t s_ucGRAM[8][128];
/*
*********************************************************************************************************
* 函 数 名: OLED_PutPixel
* 功能说明: 画1个像素
* 形 参:
* _usX,_usY : 像素坐标
* _ucColor :像素颜色
* 返 回 值: 无
*********************************************************************************************************
*/
void OLED_PutPixel(uint16_t _usX, uint16_t _usY, uint8_t _ucColor)
{
uint8_t ucValue;
uint8_t ucPageAddr;
uint8_t ucColAddr;
const uint8_t aOrTab[8] = {0x01, 0x02, 0x04, 0x08,0x10,0x20,0x40,0x80};
const uint8_t aAndTab[8] = {0xFE, 0xFD, 0xFB, 0xF7,0xEF,0xDF,0xBF,0x7F};
ucPageAddr = _usY / 8; //计算横坐标地址属于哪一页
ucColAddr = _usX; //列地址
ucValue = s_ucGRAM[ucPageAddr][ucColAddr]; //获取显存中这一字节的数据
if (_ucColor == 0) //该点不显显示
{
ucValue &= aAndTab[_usY % 8]; //将该字节对应位清零
}
else
{
ucValue |= aOrTab[_usY % 8]; //该点对应位置位
}
s_ucGRAM[ucPageAddr][ucColAddr] = ucValue; //更新显存
}
/*
*********************************************************************************************************
* 函 数 名: OLED_GetPixel
* 功能说明: 读取1个像素
* 形 参:
* _usX,_usY : 像素坐标
* 返 回 值: 颜色值 (0, 1)
*********************************************************************************************************
*/
uint8_t OLED_GetPixel(uint16_t _usX, uint16_t _usY)
{
uint8_t ucValue;
uint8_t ucPageAddr;
uint8_t ucColAddr;
ucPageAddr = _usY / 8;
ucColAddr = _usX;
ucValue = s_ucGRAM[ucPageAddr][ucColAddr];
if (ucValue & (_usY % 8))
{
return 1;
}
else
{
return 0;
}
}
oled.h
#ifndef __OLED_H
#define __OLED_H
#include "stm32f10x.h"
void OLED_PutPixel(uint16_t _usX, uint16_t _usY, uint8_t _ucColor) ; // 画1个像素
uint8_t OLED_GetPixel(uint16_t _usX, uint16_t _usY); // 读1个像素
#endif
stemwin移植要点
- iar工程文件使能crc模块
- Config文件夹下删除LCDConf_Lin_Template.c、LCDConf_Lin_Template.h,更改LCDConf_FlexColor_Template.h为LCDConf.h
- Lib文件夹下仅保留STemWin532_CM4_IAR.a(官网下载),或仅保留
- 添加内部延时函数,
stm32f4xx_it.c
#include "GUI.h" //新增
extern volatile GUI_TIMER_TIME OS_TimeMS; //新增
void SysTick_Handler(void)
{
HAL_IncTick();
OS_TimeMS++; //新增
}
- stemwin增加打点、读点函数,共修改三处,
GUIDRV_Template.c
#include "oled.h" //添加自己驱动的头文件
/*********************************************************************
*
* _SetPixelIndex
*
* Purpose:
* Sets the index of the given pixel. The upper layers
* calling this routine make sure that the coordinates are in range, so
* that no check on the parameters needs to be performed.
*/
static void _SetPixelIndex(GUI_DEVICE * pDevice, int x, int y, int PixelIndex) {
//
// Convert logical into physical coordinates (Dep. on LCDConf.h)
//
#if (LCD_MIRROR_X == 1) || (LCD_MIRROR_Y == 1) || (LCD_SWAP_XY == 1)
int xPhys, yPhys;
xPhys = LOG2PHYS_X(x, y);
yPhys = LOG2PHYS_Y(x, y);
#else
#define xPhys x
#define yPhys y
#endif
GUI_USE_PARA(pDevice);
GUI_USE_PARA(x);
GUI_USE_PARA(y);
GUI_USE_PARA(PixelIndex);
{
//修改1:插入自己的画点函数
OLED_PutPixel(x,y,PixelIndex);
}
#if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
#undef xPhys
#undef yPhys
#endif
}
/*********************************************************************
*
* _GetPixelIndex
*
* Purpose:
* Returns the index of the given pixel. The upper layers
* calling this routine make sure that the coordinates are in range, so
* that no check on the parameters needs to be performed.
*/
static unsigned int _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y) {
unsigned int PixelIndex;
//
// Convert logical into physical coordinates (Dep. on LCDConf.h)
//
#if (LCD_MIRROR_X == 1) || (LCD_MIRROR_Y == 1) || (LCD_SWAP_XY == 1)
int xPhys, yPhys;
xPhys = LOG2PHYS_X(x, y);
yPhys = LOG2PHYS_Y(x, y);
#else
#define xPhys x
#define yPhys y
#endif
GUI_USE_PARA(pDevice);
GUI_USE_PARA(x);
GUI_USE_PARA(y);
{
//插入自己的读点函数
PixelIndex = OLED_GetPixel(x,y);
}
#if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
#undef xPhys
#undef yPhys
#endif
return PixelIndex;
}
/*********************************************************************
*
* _GetDevData
*/
static void * _GetDevData(GUI_DEVICE * pDevice, int Index) {
GUI_USE_PARA(pDevice);
#if GUI_SUPPORT_MEMDEV
switch (Index) {
case LCD_DEVDATA_MEMDEV:
//return (void *)&GUI_MEMDEV_DEVICE_16;
return (void *)&GUI_MEMDEV_DEVICE_1; //将16改为1
}
#else
GUI_USE_PARA(Index);
#endif
return NULL;
}
- stemwin选择移植方式为自定义打点,
GUIDRV_FlexColor.c
#define XSIZE_PHYS 128 // 屏幕宽度
#define YSIZE_PHYS 64 // 高度
#define VXSIZE_PHYS 128 // 虚拟内存宽度
#define VYSIZE_PHYS 64 // 虚拟内存高度
/*********************************************************************
*
* LCD_X_Config
* * Function description:
* Called during the initialization process in order to set up the
* display driver configuration.
* */
void LCD_X_Config(void)
{
//GUI_DEVICE_CreateAndLink(GUIDRV_FLEXCOLOR, GUICC_565, 0, 0);
//采用设备自己定义初始化 单色屏幕,其余的写寄存器 写数据 连续读 连续写的操作都是基于彩屏或者其他驱动芯片的,直接删除就可以否则GUI会初始化失败
GUI_DEVICE_CreateAndLink(GUIDRV_TEMPLATE, GUICC_1, 0, 0);
LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS);
LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS);
}
- stemwin修改内存分配,
GUIConfig.c
#define GUI_NUMBYTES (1024*30)
- stemwin修改不必要的支持,
GUIConfig.h
#define GUI_SUPPORT_TOUCH (0) //新增,在"#ifndef GUI_SUPPORT_TOUCH"语句之前
#define GUI_SUPPORT_MOUSE (0) //修改
#define GUI_SUPPORT_MEMDEV (0) //修改
- iar堆栈大小修改,iar工程文件右键"options"->“linker”->“Config”->“Edit”->"Stack/Head
Size"中,CSTACK修改为0xA000 - 主程序进行测试,
main.c
int main()
{
...... //初始化
TNS_G12864FGDISW_60W_Init(); //spi初始化;发送显示初始化命令
GUI_Init();
GUI_DispString("1234"); //更改显存数据
DispWriteData(); //将显存写入oled
while(1)
{
}
}