一、墨水屏相关基础(摘自微雪官方)
支持局刷的屏幕,注意使用的时候不能一直用局刷对屏幕进行刷新,需要在做几次局刷之后,对屏幕进行一次全刷清屏。否则会造成屏幕显示效果异常。
注意屏幕不能长时间上电,在屏幕不刷新的时候,要将屏幕设置成睡眠模式,或者进行断电处理。否则屏幕长时间保持高电压状态,会损坏膜片,无法修复。
使用墨水屏的时候,建议刷新时间间隔至少是180s, 并且至少每24小时做一次刷新,如果长期不使用墨水屏的话,要将墨水屏刷白存放。(具体储存环境需求参考数据手册)
屏幕进入睡眠模式之后,会忽略发送的图片数据,只有重新初始化才能正常刷新。
控制 0x3C 或 0x50 (具体参照数据手册)寄存器可以调节边框颜色,在例程中可以调节 Border Waveform Control 寄存器或者 VCOM AND DATA INERTVAL SETTING 进行设置。
如果发现制作的图片数据在屏幕上显示错误,建议检查一下图片大小设置是否正确,调换一下宽度和高度设置再试一下。
墨水屏的工作电压要求是 3.3V,如果您购买的是裸屏的话,设计电路的时候如果需要配合 5V 工作环境的话,建议做一下电平转换处理。新版驱动板(Rev2.1及后续版本)加入了电平处理电路,可以同时支持 3.3V 和 5V 工作环境,老版本只能支持 3.3V 工作环境,使用的时候可以先确认一下版本号(版本号在板名下)。
屏幕的 FPC 排线比较脆弱,注意使用的时候沿屏幕水平方向弯曲排线,不可以沿屏幕垂直方向弯曲排线。
墨水屏屏幕较为脆弱,注意尽量避免跌落、碰撞、用力按压。
二、干起来
PART2 配置I/O
stm32使用HAL库配置。用I/O口模拟SPI通信。
I/O配置。
#define LED_Pin GPIO_PIN_2
#define LED_GPIO_Port GPIOA
#define INK_MOSI_Pin GPIO_PIN_5
#define INK_MOSI_GPIO_Port GPIOA
#define INK_CLK_Pin GPIO_PIN_6
#define INK_CLK_GPIO_Port GPIOA
#define INK_CS_Pin GPIO_PIN_7
#define INK_CS_GPIO_Port GPIOA
#define INK_DC_Pin GPIO_PIN_0
#define INK_DC_GPIO_Port GPIOB
#define INK_RST_Pin GPIO_PIN_1
#define INK_RST_GPIO_Port GPIOB
#define INK_IS_BUSY_Pin GPIO_PIN_8
#define INK_IS_BUSY_GPIO_Port GPIOA
#define KEY_USER_Pin GPIO_PIN_15
#define KEY_USER_GPIO_Port GPIOA
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, LED_Pin|INK_MOSI_Pin|INK_CLK_Pin
|INK_CS_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, INK_DC_Pin|INK_RST_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : LED_Pin INK_MOSI_Pin INK_CLK_Pin
INK_CS_Pin */
GPIO_InitStruct.Pin = LED_Pin||INK_MOSI_Pin|INK_CLK_Pin
|INK_CS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : INK_DC_Pin INK_RST_Pin */
GPIO_InitStruct.Pin = INK_DC_Pin|INK_RST_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : INK_IS_BUSY_Pin KEY_USER_Pin */
GPIO_InitStruct.Pin = INK_IS_BUSY_Pin|KEY_USER_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
PART2 底层硬件接口必要的调用函数
主要有设备初始化函数:int DEV_Module_Init(void);设备退出函数:void DEV_Module_Exit(void);模拟SPI度的函数void DEV_SPI_WriteByte(UBYTE value);SPI延时函数void SpiWrite(unsigned char value);
#ifndef _DEV_CONFIG_H_
#define _DEV_CONFIG_H_
#include "main.h"
//#include "stm32f1xx_hal.h"
//#include "stm32f1xx_hal_gpio.h"
#include <stdint.h>
#include <stdio.h>
extern void SpiWrite(unsigned char value);
/**
* data
**/
#define UBYTE uint8_t
#define UWORD uint16_t
#define UDOUBLE uint32_t
/**
* e-Paper GPIO
**/
#define EPD_RST_PIN INK_RST_GPIO_Port, INK_RST_Pin
#define EPD_DC_PIN INK_DC_GPIO_Port, INK_DC_Pin
#define EPD_CS_PIN INK_CS_GPIO_Port, INK_CS_Pin
#define EPD_BUSY_PIN INK_IS_BUSY_GPIO_Port, INK_IS_BUSY_Pin
#define EPD_W21_MOSI_0 HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET)
#define EPD_W21_MOSI_1 HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET)
#define EPD_W21_CLK_0 HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_RESET)
#define EPD_W21_CLK_1 HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_SET)
#define EPD_W21_CS_0 HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_RESET)
#define EPD_W21_CS_1 HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_SET)
#define EPD_W21_DC_0 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET)
#define EPD_W21_DC_1 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET)
#define EPD_W21_RST_0 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET)
#define EPD_W21_RST_1 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET)
/**
* GPIO read and write
**/
#define DEV_Digital_Write(_pin, _value) HAL_GPIO_WritePin(_pin, _value == 0? GPIO_PIN_RESET:GPIO_PIN_SET)
#define DEV_Digital_Read(_pin) HAL_GPIO_ReadPin(_pin)
/**
* delay x ms
**/
#define DEV_Delay_ms(__xms) HAL_Delay(__xms);
void DEV_SPI_WriteByte(UBYTE value);
int DEV_Module_Init(void);
void DEV_Module_Exit(void);
#endif
/********************上面是头文件中的定义,下面是c实现的函数*******************/
void SpiDelay(unsigned char xrate)
{
unsigned char i;
while (xrate)
{
for (i = 0; i < 1; i++);
xrate--;
}
}
void SpiWrite(unsigned char value)
{
unsigned char i;
SpiDelay(1);
for (i = 0; i < 8; i++)
{
EPD_W21_CLK_0;
SpiDelay(1);
if (value & 0x80)
EPD_W21_MOSI_1;
else
EPD_W21_MOSI_0;
value = (value << 1);
SpiDelay(1);
EPD_W21_CLK_1;
SpiDelay(1);
}
}
//extern SPI_HandleTypeDef hspi1;
void DEV_SPI_WriteByte(UBYTE value)
{
// HAL_SPI_Transmit(&hspi1, &value, 1, 1000);
SpiWrite(value);
}
int DEV_Module_Init(void)
{
DEV_Digital_Write(EPD_DC_PIN, 0);
DEV_Digital_Write(EPD_CS_PIN, 0);
DEV_Digital_Write(EPD_RST_PIN, 1);
return 0;
}
void DEV_Module_Exit(void)
{
DEV_Digital_Write(EPD_DC_PIN, 0);
DEV_Digital_Write(EPD_CS_PIN, 0);
//close 5V
DEV_Digital_Write(EPD_RST_PIN, 0);
}
PART3 功能函数
EPD_1in54_V2.c
#include “EPD_1in54_V2.h”
复位函数static void EPD_1IN54_V2_Reset(void)
发送命令函数static void EPD_1IN54_V2_SendCommand(UBYTE Reg)
发送数据函数static void EPD_1IN54_V2_SendData(UBYTE Data)
读空闲状态函数static void EPD_1IN54_V2_ReadBusy(void)
开启显示全屏函数static void EPD_1IN54_V2_TurnOnDisplay(void)
开启显示部分区域函数static void EPD_1IN54_V2_TurnOnDisplayPart(void)
设置显示区域函数static void EPD_1IN54_V2_SetWindows(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend)
static void EPD_1IN54_V2_Lut(UBYTE *lut)
static void EPD_1IN54_V2_SetLut(UBYTE *lut)
static void EPD_1IN54_V2_SetCursor(UWORD Xstart, UWORD Ystart)
屏幕初始化void EPD_1IN54_V2_Init(void)
屏幕局部初始化void EPD_1IN54_V2_Init_Partial(void)
屏幕清除void EPD_1IN54_V2_Clear(void)
向RAM发送显示的图像void EPD_1IN54_V2_Display(UBYTE *Image)
显示部分区域图像void EPD_1IN54_V2_DisplayPartBaseImage(UBYTE *Image)
向RAM发送部分显示图像void EPD_1IN54_V2_DisplayPart(UBYTE *Image)
屏幕休眠void EPD_1IN54_V2_Sleep(void)
测试例程int EPD_test(void)
PART4 应用函数
GUI_Paint.c中包含画点、线 、矩形等函数。使用时调用即可。
三、应用
int main(void)
{
HAL_Init();
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
EPD_1IN54_V2_Init();
EPD_1IN54_V2_Clear();
DEV_Delay_ms(500);
//Create a new image cache
UBYTE *BlackImage;
/* you have to edit the startup_stm32fxxx.s file and set a big enough heap size */
UWORD Imagesize = ((EPD_1IN54_V2_WIDTH % 8 == 0)? (EPD_1IN54_V2_WIDTH / 8 ): (EPD_1IN54_V2_WIDTH / 8 + 1)) * EPD_1IN54_V2_HEIGHT;
if((BlackImage = (UBYTE *)malloc(Imagesize)) == NULL) {
printf("Failed to apply for black memory...\r\n");
return -1;
}
printf("Paint_NewImage\r\n");
Paint_NewImage(BlackImage, EPD_1IN54_V2_WIDTH, EPD_1IN54_V2_HEIGHT, 270, WHITE);
#if 1 //show image for array
printf("show image for array\r\n");
Paint_SelectImage(BlackImage);
Paint_Clear(WHITE);
Paint_DrawBitMap(gImage_1in54);
EPD_1IN54_V2_Display(BlackImage);
DEV_Delay_ms(2000);
#endif
#if 1 // Drawing on the image
printf("Drawing\r\n");
//1.Select Image
Paint_SelectImage(BlackImage);
Paint_Clear(WHITE);
// 2.Drawing on the image
Paint_DrawPoint(5, 10, BLACK, DOT_PIXEL_1X1, DOT_STYLE_DFT);
Paint_DrawPoint(5, 25, BLACK, DOT_PIXEL_2X2, DOT_STYLE_DFT);
Paint_DrawPoint(5, 40, BLACK, DOT_PIXEL_3X3, DOT_STYLE_DFT);
Paint_DrawPoint(5, 55, BLACK, DOT_PIXEL_4X4, DOT_STYLE_DFT);
Paint_DrawLine(20, 10, 70, 60, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
Paint_DrawLine(70, 10, 20, 60, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
Paint_DrawLine(170, 15, 170, 55, BLACK, DOT_PIXEL_1X1, LINE_STYLE_DOTTED);
Paint_DrawLine(150, 35, 190, 35, BLACK, DOT_PIXEL_1X1, LINE_STYLE_DOTTED);
Paint_DrawRectangle(20, 10, 70, 60, BLACK, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
Paint_DrawRectangle(85, 10, 130, 60, BLACK, DOT_PIXEL_1X1, DRAW_FILL_FULL);
Paint_DrawCircle(170, 35, 20, BLACK, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
Paint_DrawCircle(170, 85, 20, BLACK, DOT_PIXEL_1X1, DRAW_FILL_FULL);
Paint_DrawString_EN(5, 85, "waveshare", &Font20, BLACK, WHITE);
Paint_DrawNum(5, 110, 123456789, &Font20, BLACK, WHITE);
Paint_DrawString_CN(5, 135,"���abc", &Font12CN, BLACK, WHITE);
Paint_DrawString_CN(5, 155, "ѩ����", &Font24CN, WHITE, BLACK);
EPD_1IN54_V2_Display(BlackImage);
DEV_Delay_ms(2000);
#endif
#if 1 //Partial refresh, example shows time
// The image of the previous frame must be uploaded, otherwise the
// first few seconds will display an exception.
EPD_1IN54_V2_DisplayPartBaseImage(BlackImage);
// enter partial mode
EPD_1IN54_V2_Init_Partial();
printf("Partial refresh\r\n");
Paint_SelectImage(BlackImage);
PAINT_TIME sPaint_time;
sPaint_time.Hour = 12;
sPaint_time.Min = 34;
sPaint_time.Sec = 56;
UBYTE num = 10;
for (;;) {
sPaint_time.Sec = sPaint_time.Sec + 1;
if (sPaint_time.Sec == 60) {
sPaint_time.Min = sPaint_time.Min + 1;
sPaint_time.Sec = 0;
if (sPaint_time.Min == 60) {
sPaint_time.Hour = sPaint_time.Hour + 1;
sPaint_time.Min = 0;
if (sPaint_time.Hour == 24) {
sPaint_time.Hour = 0;
sPaint_time.Min = 0;
sPaint_time.Sec = 0;
}
}
}
Paint_ClearWindows(15, 65, 15 + Font20.Width * 7, 65 + Font20.Height, WHITE);
Paint_DrawTime(15, 65, &sPaint_time, &Font20, WHITE, BLACK);
num = num - 1;
if(num == 0) {
break;
}
EPD_1IN54_V2_DisplayPart(BlackImage);
DEV_Delay_ms(500);//Analog clock 1s
}
#endif
printf("Clear...\r\n");
EPD_1IN54_V2_Init();
EPD_1IN54_V2_Clear();
printf("Goto Sleep...\r\n");
EPD_1IN54_V2_Sleep();
free(BlackImage);
BlackImage = NULL;
// close 5V
printf("close 5V, Module enters 0 power consumption ...\r\n");
DEV_Module_Exit();
/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
while (1) {
HAL_Delay(10000);
}
}
当然,还有需要的字体文件等。。。
注意
注意:由于使用malloc开辟空间,stm32启动文件中默认的空间不足,该函数返回null导致编译能过,但运行不下去。
对于malloc和free对内存堆栈块的空间操作,在keilMDK中需要满足下面几个条件:
1、使用的代码文件中需要包含头文件 <stdlib.h>
2、在工程的属性设置中需要把 Use MicroLIB 选项勾选,如下图。
3、这时候原则上就可以使用空间申请和释放的两个操作函数了,但是由于STM32在startup_stm32f10x_hd.s中分配的堆空间只有0x00000200个字节,所以很多时候调用malloc函数时如果申请空间超过0X200则返回了NULL,这时候就需要到该文件对这个值进行设置。
上面工作完成后,我们就可以愉快地尽情使用malloc和free两个函数了!!
修改启动文件startup_stm32l051xx.s,将堆栈大小由默认200改为大于5000,不够的话在稍微大一点。文章来源:https://www.toymoban.com/news/detail-425063.html
**代码下载:**
https://download.csdn.net/download/weber33/87020361文章来源地址https://www.toymoban.com/news/detail-425063.html
到了这里,关于stm32驱动微雪墨水屏1.54inch e-Paper V2的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!