这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【换取手持数字示波器】+精英板驱动LCD屏

共7条 1/1 1 跳转至

【换取手持数字示波器】+精英板驱动LCD屏

专家
2024-04-10 21:00:44   被打赏 50 分(兑奖)     打赏

       相信大家对正点原子推出的精英板不陌生吧,作为一款入门STM32的高性价比开发板,可以练习许多开发应用。本次分享就精英板V2驱动LCD彩屏外设展开话题。正点原子精英STM32开发板选择的是STM32F103ZET6作为MCU,该芯片是STM32F103里面配置非常强大的了,它拥有的资源包括:64KB SRAM、512KB FLASH、2个基本定时器、4个通用定时器、2个高级定时器、2个DMA控制器(共12个通道)、3个 SPI、2个IIC、5个串口、1个USB、1个CAN、3个12位ADC、1个12位DAC、1个SDIO接口、1个FSMC接口以及112个通用IO口。该芯片的配置十分强悍,并且还带外部总线(FSMC)可以用来外扩SRAM和连接LCD等,通过FSMC驱动LCD,可以显著提高LCD的刷屏速度,是STM32F1家族常用型号里面,最高配置的芯片了。

精英板V2硬件点位图.png        本次驱动的LCD屏并不是正点原子提供的,而是采用另外一个扩展板,通过GPIO去模拟SPI通讯,因此不占用精英板上的TFT_LCD固定硬件接口。这里不得不谈及这块扩展板,扩展板上的资源也很丰富,有集成多个传感器,包括温湿度传感器、三轴磁场传感器、加速度角速度传感器、环境光传感器,一个RGB彩灯、一块128*160分辨率的电阻式触摸屏,一个旋钮,一个双轴电位计摇杆。当然此次分享就触摸屏的显示驱动部分进行讲解。

扩展板.png      本次采用JLink调试器与精英板相连接,扩展板上的触摸屏通过杜邦线与精英板相连接。两者之间的关联可通过下方的原理图可知。

扩展板原理图.png精英板部分原理图.png        在硬件连线的基础上进行代码编写,这里我们采用GPIO模拟SPI通讯,屏的芯片是基于ST7735S的,因此我们在基础工程框架中增加驱动代码,部分参考代码如下:

lcd_init.h

#ifndef __LCD_INIT_H
#define __LCD_INIT_H

#include "stm32f1xx.h"
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"

#define USE_HORIZONTAL 1  //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int  u32;


#if USE_HORIZONTAL==0||USE_HORIZONTAL==1
#define LCD_W 128
#define LCD_H 160

#else
#define LCD_W 160
#define LCD_H 128
#endif

#define BOARD_LCD_GPIO GPIOA
#define BOARD_LCD_GPIO_SCLK_PIN GPIO_PIN_0
#define BOARD_LCD_GPIO_CS_PIN   GPIO_PIN_1
#define BOARD_LCD_GPIO_MOSI_PIN GPIO_PIN_4
#define BOARD_LCD_GPIO_DC_PIN   GPIO_PIN_5
#define BOARD_LCD_GPIO_RES_PIN  GPIO_PIN_6
#define BOARD_LCD_BLK_GPIO GPIOA
#define BOARD_LCD_GPIO_BLK_PIN  GPIO_PIN_7

//-----------------LCD端口定义----------------
#define LCD_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)             /* PB口时钟使能 */

#define LCD_SCLK_Clr() HAL_GPIO_WritePin(BOARD_LCD_GPIO,BOARD_LCD_GPIO_SCLK_PIN,GPIO_PIN_RESET)//SCL SCLK
#define LCD_SCLK_Set() HAL_GPIO_WritePin(BOARD_LCD_GPIO,BOARD_LCD_GPIO_SCLK_PIN,GPIO_PIN_SET)

#define LCD_CS_Clr()   HAL_GPIO_WritePin(BOARD_LCD_GPIO,BOARD_LCD_GPIO_CS_PIN,GPIO_PIN_RESET)//CS
#define LCD_CS_Set()   HAL_GPIO_WritePin(BOARD_LCD_GPIO,BOARD_LCD_GPIO_CS_PIN,GPIO_PIN_SET)

#define LCD_MOSI_Clr() HAL_GPIO_WritePin(BOARD_LCD_GPIO,BOARD_LCD_GPIO_MOSI_PIN,GPIO_PIN_RESET)//SDA MOSI
#define LCD_MOSI_Set() HAL_GPIO_WritePin(BOARD_LCD_GPIO,BOARD_LCD_GPIO_MOSI_PIN,GPIO_PIN_SET)

#define LCD_DC_Clr()   HAL_GPIO_WritePin(BOARD_LCD_GPIO,BOARD_LCD_GPIO_DC_PIN,GPIO_PIN_RESET)//DC
#define LCD_DC_Set()   HAL_GPIO_WritePin(BOARD_LCD_GPIO,BOARD_LCD_GPIO_DC_PIN,GPIO_PIN_SET)

#define LCD_RES_Clr()  HAL_GPIO_WritePin(BOARD_LCD_GPIO,BOARD_LCD_GPIO_RES_PIN,GPIO_PIN_RESET)//RES
#define LCD_RES_Set()  HAL_GPIO_WritePin(BOARD_LCD_GPIO,BOARD_LCD_GPIO_RES_PIN,GPIO_PIN_SET)

#define LCD_BLK_Clr()  HAL_GPIO_WritePin(BOARD_LCD_BLK_GPIO,BOARD_LCD_GPIO_BLK_PIN,GPIO_PIN_RESET)//BLK
#define LCD_BLK_Set()  HAL_GPIO_WritePin(BOARD_LCD_BLK_GPIO,BOARD_LCD_GPIO_BLK_PIN,GPIO_PIN_SET)


void LCD_GPIO_Init(void);//初始化GPIO
void LCD_Writ_Bus(u8 dat);//模拟SPI时序
void LCD_WR_DATA8(u8 dat);//写入一个字节
void LCD_WR_DATA(u16 dat);//写入两个字节
void LCD_WR_REG(u8 dat);//写入一个指令
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2);//设置坐标函数
void LCD_Init(void);//LCD初始化
#endif

lcd_init.c

#include "lcd_init.h"
#include "stm32f1xx.h"

/******************************************************************************
      函数说明:LCD串行数据写入函数
      入口数据:dat  要写入的串行数据
      返回值:  无
******************************************************************************/
void LCD_Writ_Bus(u8 dat) 
{	
	u8 i;
	LCD_CS_Clr();
	for(i=0;i<8;i++)
	{			  
		LCD_SCLK_Clr();
		if(dat&0x80)
		{
		   LCD_MOSI_Set();
		}
		else
		{
		   LCD_MOSI_Clr();
		}
		LCD_SCLK_Set();
		dat<<=1;
	}	
  LCD_CS_Set();	
}

/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:  无
******************************************************************************/
void LCD_WR_DATA8(u8 dat)
{
	LCD_Writ_Bus(dat);
}

/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:  无
******************************************************************************/
void LCD_WR_DATA(u16 dat)
{
	LCD_Writ_Bus(dat>>8);
	LCD_Writ_Bus(dat);
}

/******************************************************************************
      函数说明:LCD写入命令
      入口数据:dat 写入的命令
      返回值:  无
******************************************************************************/
void LCD_WR_REG(u8 dat)
{
	LCD_DC_Clr();//写命令
	LCD_Writ_Bus(dat);
	LCD_DC_Set();//写数据
}


/******************************************************************************
      函数说明:设置起始和结束地址
      入口数据:x1,x2 设置列的起始和结束地址
                y1,y2 设置行的起始和结束地址
      返回值:  无
******************************************************************************/
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
{
	if(USE_HORIZONTAL==0)
	{
		LCD_WR_REG(0x2a);//列地址设置
		LCD_WR_DATA(x1+2);
		LCD_WR_DATA(x2+2);
		LCD_WR_REG(0x2b);//行地址设置
		LCD_WR_DATA(y1+1);
		LCD_WR_DATA(y2+1);
		LCD_WR_REG(0x2c);//储存器写
	}
	else if(USE_HORIZONTAL==1)
	{
		LCD_WR_REG(0x2a);//列地址设置
		LCD_WR_DATA(x1+2);
		LCD_WR_DATA(x2+2);
		LCD_WR_REG(0x2b);//行地址设置
		LCD_WR_DATA(y1+1);
		LCD_WR_DATA(y2+1);
		LCD_WR_REG(0x2c);//储存器写
	}
	else if(USE_HORIZONTAL==2)
	{
		LCD_WR_REG(0x2a);//列地址设置
		LCD_WR_DATA(x1+1);
		LCD_WR_DATA(x2+1);
		LCD_WR_REG(0x2b);//行地址设置
		LCD_WR_DATA(y1+2);
		LCD_WR_DATA(y2+2);
		LCD_WR_REG(0x2c);//储存器写
	}
	else
	{
		LCD_WR_REG(0x2a);//列地址设置
		LCD_WR_DATA(x1+1);
		LCD_WR_DATA(x2+1);
		LCD_WR_REG(0x2b);//行地址设置
		LCD_WR_DATA(y1+2);
		LCD_WR_DATA(y2+2);
		LCD_WR_REG(0x2c);//储存器写
	}
}

void LCD_Init(void)
{
	LCD_GPIO_CLK_ENABLE();   
	GPIO_InitTypeDef gpio_init_struct;
	gpio_init_struct.Pin = BOARD_LCD_GPIO_SCLK_PIN|BOARD_LCD_GPIO_CS_PIN|BOARD_LCD_GPIO_MOSI_PIN|\
	BOARD_LCD_GPIO_DC_PIN|BOARD_LCD_GPIO_RES_PIN|BOARD_LCD_GPIO_BLK_PIN;                   /* LED0引脚 */
        gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;            /* 推挽输出 */
        gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */
        HAL_GPIO_Init(BOARD_LCD_GPIO, &gpio_init_struct);       /* 初始化LCD引脚 */
	delay_ms(20);
	LCD_RES_Clr();//复位
	delay_ms(1);
	LCD_RES_Set();
	delay_ms(1);
	
	LCD_BLK_Set();//打开背光
	delay_ms(120);
	
	LCD_WR_REG(0x11); //Sleep out 
	delay_ms(120);             
	
	LCD_WR_REG(0xB1); 
	LCD_WR_DATA8(0x05); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_REG(0xB2); 
	LCD_WR_DATA8(0x05);
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_REG(0xB3); 
	LCD_WR_DATA8(0x05); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x05); 
	LCD_WR_DATA8(0x3C); 
	LCD_WR_DATA8(0x3C); 
	
	LCD_WR_REG(0xB4); //Dot inversion 
	LCD_WR_DATA8(0x03); 
	 
	LCD_WR_REG(0xC0); 
	LCD_WR_DATA8(0x28); 
	LCD_WR_DATA8(0x08); 
	LCD_WR_DATA8(0x04); 
	LCD_WR_REG(0xC1); 
	LCD_WR_DATA8(0XC0); 
	LCD_WR_REG(0xC2); 
	LCD_WR_DATA8(0x0D); 
	LCD_WR_DATA8(0x00); 
	LCD_WR_REG(0xC3); 
	LCD_WR_DATA8(0x8D); 
	LCD_WR_DATA8(0x2A); 
	LCD_WR_REG(0xC4); 
	LCD_WR_DATA8(0x8D); 
	LCD_WR_DATA8(0xEE); 
	 
	LCD_WR_REG(0xC5); //VCOM 
	LCD_WR_DATA8(0x1A); 
	LCD_WR_REG(0x36); //MX, MY, RGB mode 
	if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x00);
	else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC0);
	else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x70);
	else LCD_WR_DATA8(0xA0); 
	
	LCD_WR_REG(0xE0); 
	LCD_WR_DATA8(0x04); 
	LCD_WR_DATA8(0x22); 
	LCD_WR_DATA8(0x07); 
	LCD_WR_DATA8(0x0A); 
	LCD_WR_DATA8(0x2E); 
	LCD_WR_DATA8(0x30); 
	LCD_WR_DATA8(0x25); 
	LCD_WR_DATA8(0x2A); 
	LCD_WR_DATA8(0x28); 
	LCD_WR_DATA8(0x26); 
	LCD_WR_DATA8(0x2E); 
	LCD_WR_DATA8(0x3A); 
	LCD_WR_DATA8(0x00); 
	LCD_WR_DATA8(0x01); 
	LCD_WR_DATA8(0x03); 
	LCD_WR_DATA8(0x13); 
	LCD_WR_REG(0xE1); 
	LCD_WR_DATA8(0x04); 
	LCD_WR_DATA8(0x16); 
	LCD_WR_DATA8(0x06); 
	LCD_WR_DATA8(0x0D); 
	LCD_WR_DATA8(0x2D); 
	LCD_WR_DATA8(0x26); 
	LCD_WR_DATA8(0x23); 
	LCD_WR_DATA8(0x27); 
	LCD_WR_DATA8(0x27); 
	LCD_WR_DATA8(0x25); 
	LCD_WR_DATA8(0x2D); 
	LCD_WR_DATA8(0x3B); 
	LCD_WR_DATA8(0x00); 
	LCD_WR_DATA8(0x01); 
	LCD_WR_DATA8(0x04); 
	LCD_WR_DATA8(0x13); 
	
	LCD_WR_REG(0x3A); 
	LCD_WR_DATA8(0x05); 
	LCD_WR_REG(0x29); 
}

lcd.h

#ifndef __LCD_H
#define __LCD_H		

#include "stm32f1xx.h"
#include "lcd_init.h"

#define LCD_WIDTH   128
#define LCD_HEIGHT  160

typedef struct
{
    unsigned int index;
    unsigned int value[64];
}LCD_Plot_Data;

struct drv_lcd_coordinate
{
    int8_t ymin;
    int8_t ymax;
    uint8_t x;
    uint8_t y;
    uint8_t xsize;
    uint8_t ysize;
};

void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color);//指定区域填充颜色
void LCD_DrawPoint(u16 x,u16 y,u16 color);//在指定位置画一个点
void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color);//在指定位置画一条线
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color);//在指定位置画一个矩形
void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color);//在指定位置画一个圆
void LCD_ShowChinese(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示汉字串
void LCD_ShowChinese12x12(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个12x12汉字
void LCD_ShowChinese16x16(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个16x16汉字
void LCD_ShowChinese24x24(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个24x24汉字
void LCD_ShowChinese32x32(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个32x32汉字
void LCD_ShowChar(u16 x,u16 y,u8 num,u16 fc,u16 bc,u8 sizey,u8 mode);//显示一个字符
void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 fc,u16 bc,u8 sizey,u8 mode);//显示字符串
void LCD_ShowIntNum(u16 x,u16 y,u16 num,u8 len,u16 fc,u16 bc,u8 sizey);//显示整数变量
void LCD_ShowFloatNum1(u16 x,u16 y,float num,u8 len,u16 fc,u16 bc,u8 sizey);//显示两位小数变量
void LCD_ShowPicture(u16 x,u16 y,u16 length,u16 width,const u8 pic[]);//显示图片
u32 mypow(u8 m,u8 n);//求幂
void Plot_Data_Add(LCD_Plot_Data *Plot_Data, u32 Data);//曲线绘制结构体
void LCD_Draw_Plot(LCD_Plot_Data *Plot_Data, u32 color);//曲线绘制函数
void drv_lcd_draw_line_with_color(u16 xbegin, u16 ybegin, u16 xend, u16 yend, u16 color);
void drv_lcd_draw_coordinate_with_color(struct drv_lcd_coordinate *coord, u8 x, u8 y, u8 xsize, u8 ysize, u16 color);
void drv_lcd_draw_coordinate(struct drv_lcd_coordinate *coord, u8 x, u8 y, u8 xsize, u8 ysize);
void drv_lcd_draw_coordinate_point_with_color(struct drv_lcd_coordinate *coord, int8_t *buf, u8 num, u16 color);
void drv_lcd_coordinate_create(struct drv_lcd_coordinate *coord, int8_t ymin, int8_t ymax);

//画笔颜色
#define WHITE         	 0xFFFF
#define BLACK         	 0x0000	  
#define BLUE           	 0x001F  
#define BRED             0XF81F
#define GRED 		 0XFFE0
#define GBLUE	         0X07FF
#define RED           	 0xF800
#define MAGENTA       	 0xF81F
#define GREEN         	 0x07E0
#define CYAN          	 0x7FFF
#define YELLOW        	 0xFFE0
#define BROWN 		 0XBC40 //棕色
#define BRRED 		 0XFC07 //棕红色
#define GRAY  		 0X8430 //灰色
#define DARKBLUE      	 0X01CF	//深蓝色
#define LIGHTBLUE      	 0X7D7C	//浅蓝色
#define GRAYBLUE       	 0X5458 //灰蓝色
#define LIGHTGREEN     	 0X841F //浅绿色
#define LGRAY 		 0XC618 //浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE        0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE           0X2B12 //浅棕蓝色(选择条目的反色)

#endif

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/LCD/lcd_init.h"

int main(void)
{
    static uint8_t num = 0;
   
    HAL_Init();                                         /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);                 /* 设置时钟, 72Mhz */
    delay_init(72);                                     /* 延时初始化 */
    usart_init(115200);                                 /* 串口初始化为115200 */
    led_init();                                         /* 初始化LED */
    LCD_Init();                                         /* 初始化LCD */

    while (1)
    {
        switch (num)
        {
        case 0:
		LCD_Fill(0,0,LCD_W,LCD_H,WHITE);
            break;

        case 1:
		LCD_Fill(0,0,LCD_W,LCD_H,BLACK);
            break;

        case 2:
		LCD_Fill(0,0,LCD_W,LCD_H,BLUE);
            break;

        case 3:
		LCD_Fill(0,0,LCD_W,LCD_H,RED);
            break;

        case 4:
		LCD_Fill(0,0,LCD_W,LCD_H,MAGENTA);
            break;

        case 5:
		LCD_Fill(0,0,LCD_W,LCD_H,GREEN);
            break;

        case 6:
		LCD_Fill(0,0,LCD_W,LCD_H,CYAN);
            break;

        case 7:
		LCD_Fill(0,0,LCD_W,LCD_H,YELLOW);
            break;

        case 8:
		LCD_Fill(0,0,LCD_W,LCD_H,BRRED);
            break;

        case 9:
		LCD_Fill(0,0,LCD_W,LCD_H,GRAY);
            break;

        case 10:
		LCD_Fill(0,0,LCD_W,LCD_H,LGRAY);
            break;

        case 11:
		LCD_Fill(0,0,LCD_W,LCD_H,BROWN);
            break;
        }
        LCD_ShowChinese(30,20,"0",RED,WHITE,16,0);
        LCD_ShowChinese(46,20,"1",RED,WHITE,16,0);
        LCD_ShowChinese(62,20,"2",RED,WHITE,16,0);
        LCD_ShowChinese(78,20,"3",RED,WHITE,16,0);
        LCD_ShowString(10, 50, (const u8 *)"STM32F103ZET6", RED, WHITE, 16, 0);
        LCD_ShowString(10, 80, (const u8 *)"TFTLCD TEST", RED,WHITE, 16, 0);
        LCD_ShowString(10, 110, (const u8 *)"EEPW.COM.CN", RED, WHITE, 16, 0);
        num++;
        if (num == 12)
            num = 0;

        LED0_TOGGLE(); /*红灯闪烁*/
        delay_ms(500);
    }
}

        精英板与扩展板及调试器实物连线如下:

实物连线.jpg      扩展板上的触摸显示屏会依次循环刷出12种颜色的背景,展示如下图所示,具体移步优酷:https://v.youku.com/v_show/id_XNjM4MTQ4ODQ4OA==.html

扩展板显示.jpg




关键词: 换取手持数字示波器     STM32F103ZET6    

专家
2024-04-12 15:06:31     打赏
2楼

回复看看


专家
2024-04-17 08:55:12     打赏
3楼

谢谢分享


工程师
2024-04-18 08:56:37     打赏
4楼

谢谢分享,学习了。


助工
2024-04-24 15:43:24     打赏
5楼

如何换取的


助工
2024-05-04 18:11:50     打赏
6楼

发现硬禾这板子还挺多人用的


专家
2024-05-11 07:41:16     打赏
7楼

谢谢分享,学习了


共7条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]