基于cubemx的stm32HAL库SPI通信写LCD显示屏

2023-11-16

之前学习了如何使用LCD,记录一下,关于spi部分是从野火的资料中截取,也会加入我自己的备注,便于理解,代码部分在后面,请耐心看完。

一.SPI协议简介

SPI 协议是由摩托罗拉公司提出的通讯协议 (Serial Peripheral Interface),即串行外围设备接口,是一种高速全双工的通信总线。它被广泛地使用在 ADC、LCD 等设备与 MCU 间,要求通讯速率较高的场合。

SPI通讯系统

SPI 通讯使用 3 条总线及片选线,3 条总线分别为 SCK、MOSI、MISO,片选线为 SS ,它们的作
用介绍如下:
(1) SS( Slave Select)
从设备选择信号线,常称为片选信号线,也称为 NSS、CS,以下用 NSS表示。当有多个 SPI 从设备与 SPI 主机相连时,设备的其它信号线 SCK、MOSI 及 MISO同时并联到相同的 SPI 总线上,即无论有多少个从设备,都共同只使用这 3 条总线;而每个从设备都有独立的这一条 NSS 信号线,本信号线独占主机的一个引脚,即有多少个从设备,就有多少条片选信号线。I2C 协议中通过设备地址来寻址、选中总线上的某个设备并与其进行通讯;而 SPI 协议中没有设备地址,它使用 NSS 信号线来寻址,当主机要选择从设备时,把该从设备的 NSS 信号线设置为低电平,该从设备即被选中,即片选有效,接着主机开始与被选中的从设备进行 SPI 通讯。所以 SPI 通讯以 NSS 线置低电平为开始信号,以NSS 线被拉高作为结束信号。在LCD中,片选线有很多名称,CS,SS,NSS都是指片选)

(2) SCK (Serial Clock):
时钟信号线,用于通讯数据同步。它由通讯主机产生,决定了通讯的速率,不同的设备支持的最高时钟频率不一样,如 STM32 的 SPI 时钟频率最大为 fpclk/2,两个设备之间通讯时,通讯速率受限于低速设备。
(3) MOSI (Master Output,Slave Input):
主设备输出/从设备输入引脚。主机的数据从这条信号线
输出,从机由这条信号线读入主机发送的数据,即这条线上数据的方向为主机到从机。
(与IIC相比,这个就是信号线,由主机向从机发送数据,即SDA)
(4) MISO(Master Input,,Slave Output):
主设备输入/从设备输出引脚。主机从这条信线读入数据,
从机的数据由这条信号线输出到主机,即在这条线上数据的方向为从机到主机。
(从机向主机发送数据,使用触摸屏时需要这根线)。

SPI时序图

在这里插入图片描述
CS 信号线由高变低,是 SPI 通讯的起始信号,CS 信号由低变高,是 SPI 通讯的停止信号。SPI 使用 MOSI 及 MISO 信号线来传输数据,使用 SCK 信号线进行数据同步。MOSI 及 MISO 数据线在 SCK 的每个时钟周期传输一位数据。

二.LCD请添加图片描述

数据线,时钟线,片选线都有,分别对应SDA,SCL,CS,还有两根线是DC,数据命令选择;RES液晶复位;BL,背光选择。在淘宝商家处都有详细资料。

三.代码

我的代码是移植淘宝卖家发的资料,接下来说一下要改的部分。
1.在cubemx 中对引脚的配置如下,可以自己选择空闲的引脚,配置为output。
在这里插入图片描述
2.将代码拆分为通讯时序和显示函数两个部分。

#include "SPI_LCD.h"
#include "main.h"
#include "string.h"

 
//管理LCD重要参数
//默认为竖屏
_lcd_dev lcddev;

//画笔颜色,背景颜色
u16 POINT_COLOR = 0x0000,BACK_COLOR = 0xFFFF;  
u16 DeviceCode;	 
	
/*SPI写数据*/
void  SPIv_WriteData(u8 Data)
{
	unsigned char i=0;
	for(i=8;i>0;i--)
	{
	  if(Data&0x80)	
		{
	  SPI_MOSI_SET; //输出数据
		}
    else 
		{
			SPI_MOSI_CLR;
		}
	   
      SPI_SCLK_CLR;       
      SPI_SCLK_SET;
      Data<<=1; 
	}
}


/*****************************************************************************
 * @name       :void LCD_WR_REG(u8 data)
 * @date       :2018-08-09 
 * @function   :Write an 8-bit command to the LCD screen
 * @parameters :data:Command value to be written
 * @retvalue   :None
******************************************************************************/
void LCD_WR_REG(u8 data)
{ 
   LCD_CS_CLR;     
	 LCD_RS_CLR;	  
   SPIv_WriteData(data);
   LCD_CS_SET;	
}

/*****************************************************************************
 * @name       :void LCD_WR_DATA(u8 data)
 * @date       :2018-08-09 
 * @function   :Write an 8-bit data to the LCD screen
 * @parameters :data:data value to be written
 * @retvalue   :None
******************************************************************************/
void LCD_WR_DATA(u8 data)
{
   LCD_CS_CLR;
	 LCD_RS_SET;
   SPIv_WriteData(data);
   LCD_CS_SET;
}

/*****************************************************************************
 * @name       :void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue)
 * @date       :2018-08-09 
 * @function   :Write data into registers
 * @parameters :LCD_Reg:Register address
                LCD_RegValue:Data to be written
 * @retvalue   :None
******************************************************************************/
void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue)
{	
	LCD_WR_REG(LCD_Reg);  
	LCD_WR_DATA(LCD_RegValue);	    		 
}	   

/*****************************************************************************
 * @name       :void LCD_WriteRAM_Prepare(void)
 * @date       :2018-08-09 
 * @function   :Write GRAM
 * @parameters :None
 * @retvalue   :None
******************************************************************************/	 
void LCD_WriteRAM_Prepare(void)
{
	LCD_WR_REG(lcddev.wramcmd);
}	 

/*****************************************************************************
 * @name       :void Lcd_WriteData_16Bit(u16 Data)
 * @date       :2018-08-09 
 * @function   :Write an 16-bit command to the LCD screen
 * @parameters :Data:Data to be written
 * @retvalue   :None
******************************************************************************/	 
void Lcd_WriteData_16Bit(u16 Data)
{	
   LCD_CS_CLR;
   LCD_RS_SET;  
   SPIv_WriteData(Data>>8);
	 SPIv_WriteData(Data);
   LCD_CS_SET;
}

/*****************************************************************************
 * @name       :void LCD_DrawPoint(u16 x,u16 y)
 * @date       :2018-08-09 
 * @function   :Write a pixel data at a specified location
 * @parameters :x:the x coordinate of the pixel
                y:the y coordinate of the pixel
 * @retvalue   :None
******************************************************************************/	
void LCD_DrawPoint(u16 x,u16 y)
{
	LCD_SetCursor(x,y);//设置光标位置 
	Lcd_WriteData_16Bit(POINT_COLOR); 
}

/*****************************************************************************
 * @name       :void LCD_Clear(u16 Color)
 * @date       :2018-08-09 
 * @function   :Full screen filled LCD screen
 * @parameters :color:Filled color
 * @retvalue   :None
******************************************************************************/	

void LCD_Clear(u16 Color)
{
  unsigned int i,m;  
	LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);   
	LCD_CS_CLR;
	LCD_RS_SET;
	for(i=0;i<lcddev.height;i++)
	{
    for(m=0;m<lcddev.width;m++)
    {	
			Lcd_WriteData_16Bit(Color);
		}
	}
	 LCD_CS_SET;
} 


/*****************************************************************************
 * @name       :void LCD_RESET(void)
 * @date       :2018-08-09 
 * @function   :Reset LCD screen
 * @parameters :None
 * @retvalue   :None
******************************************************************************/	
void LCD_RESET(void)
{
	LCD_RST_CLR;
	HAL_Delay(100);	
	LCD_RST_SET;
	HAL_Delay(50);
}

/*****************************************************************************
 * @name       :void LCD_Init(void)
 * @date       :2018-08-09 
 * @function   :Initialization LCD screen
 * @parameters :None
 * @retvalue   :None
******************************************************************************/	 	 
void LCD_Init(void)
{ 
	//MX_GPIO_Init();
 	LCD_RESET(); //LCD 复位
//************* ST7735S初始化**********//	
	LCD_WR_REG(0x11);//Sleep exit 
	HAL_Delay(150);		
	//ST7735R Frame Rate
	LCD_WR_REG(0xB1); 
	LCD_WR_DATA(0x01); 
	LCD_WR_DATA(0x2C); 
	LCD_WR_DATA(0x2D); 
	LCD_WR_REG(0xB2); 
	LCD_WR_DATA(0x01); 
	LCD_WR_DATA(0x2C); 
	LCD_WR_DATA(0x2D); 
	LCD_WR_REG(0xB3); 
	LCD_WR_DATA(0x01); 
	LCD_WR_DATA(0x2C); 
	LCD_WR_DATA(0x2D); 
	LCD_WR_DATA(0x01); 
	LCD_WR_DATA(0x2C); 
	LCD_WR_DATA(0x2D); 	
	LCD_WR_REG(0xB4); //Column inversion 
	LCD_WR_DATA(0x07); 	
	//ST7735R Power Sequence
	LCD_WR_REG(0xC0); 
	LCD_WR_DATA(0xA2); 
	LCD_WR_DATA(0x02); 
	LCD_WR_DATA(0x84); 
	LCD_WR_REG(0xC1); 
	LCD_WR_DATA(0xC5); 
	LCD_WR_REG(0xC2); 
	LCD_WR_DATA(0x0A); 
	LCD_WR_DATA(0x00); 
	LCD_WR_REG(0xC3); 
	LCD_WR_DATA(0x8A); 
	LCD_WR_DATA(0x2A); 
	LCD_WR_REG(0xC4); 
	LCD_WR_DATA(0x8A); 
	LCD_WR_DATA(0xEE); 
	LCD_WR_REG(0xC5); //VCOM 
	LCD_WR_DATA(0x0E); 	
	LCD_WR_REG(0x36); //MX, MY, RGB mode 
	LCD_WR_DATA(0xC0); 
	//ST7735R Gamma Sequence
	LCD_WR_REG(0xe0); 
	LCD_WR_DATA(0x0f); 
	LCD_WR_DATA(0x1a); 
	LCD_WR_DATA(0x0f); 
	LCD_WR_DATA(0x18); 
	LCD_WR_DATA(0x2f); 
	LCD_WR_DATA(0x28); 
	LCD_WR_DATA(0x20); 
	LCD_WR_DATA(0x22); 
	LCD_WR_DATA(0x1f); 
	LCD_WR_DATA(0x1b); 
	LCD_WR_DATA(0x23); 
	LCD_WR_DATA(0x37); 
	LCD_WR_DATA(0x00); 	
	LCD_WR_DATA(0x07); 
	LCD_WR_DATA(0x02); 
	LCD_WR_DATA(0x10); 
	LCD_WR_REG(0xe1); 
	LCD_WR_DATA(0x0f); 
	LCD_WR_DATA(0x1b); 
	LCD_WR_DATA(0x0f); 
	LCD_WR_DATA(0x17); 
	LCD_WR_DATA(0x33); 
	LCD_WR_DATA(0x2c); 
	LCD_WR_DATA(0x29); 
	LCD_WR_DATA(0x2e); 
	LCD_WR_DATA(0x30); 
	LCD_WR_DATA(0x30); 
	LCD_WR_DATA(0x39); 
	LCD_WR_DATA(0x3f); 
	LCD_WR_DATA(0x00); 
	LCD_WR_DATA(0x07); 
	LCD_WR_DATA(0x03); 
	LCD_WR_DATA(0x10);  	
	LCD_WR_REG(0x2a);
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(0x7f);
	LCD_WR_REG(0x2b);
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(0x9f);
	LCD_WR_REG(0xF0); //Enable test command  
	LCD_WR_DATA(0x01); 
	LCD_WR_REG(0xF6); //Disable ram power save mode 
	LCD_WR_DATA(0x00); 	
	LCD_WR_REG(0x3A); //65k mode 
	LCD_WR_DATA(0x05); 
	LCD_WR_REG(0x29);//Display on	 	
  LCD_direction(USE_HORIZONTAL);//设置LCD显示方向
	LCD_BLK_SET;//点亮背光	 
	LCD_Clear(WHITE);//清全屏白色
}
 
/*****************************************************************************
 * @name       :void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
 * @date       :2018-08-09 
 * @function   :Setting LCD display window
 * @parameters :xStar:the bebinning x coordinate of the LCD display window
								yStar:the bebinning y coordinate of the LCD display window
								xEnd:the endning x coordinate of the LCD display window
								yEnd:the endning y coordinate of the LCD display window
 * @retvalue   :None
******************************************************************************/ 
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
{	
	LCD_WR_REG(lcddev.setxcmd);	
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(xStar);		
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(xEnd);

	LCD_WR_REG(lcddev.setycmd);	
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(yStar);		
	LCD_WR_DATA(0x00);
	LCD_WR_DATA(yEnd);

	LCD_WriteRAM_Prepare();	//开始写入GRAM			
}   

/*****************************************************************************
 * @name       :void LCD_SetCursor(u16 Xpos, u16 Ypos)
 * @date       :2018-08-09 
 * @function   :Set coordinate value
 * @parameters :Xpos:the  x coordinate of the pixel
								Ypos:the  y coordinate of the pixel
 * @retvalue   :None
******************************************************************************/ 
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{	  	    			
	LCD_SetWindows(Xpos,Ypos,Xpos,Ypos);	
} 

/*****************************************************************************
 * @name       :void LCD_direction(u8 direction)
 * @date       :2018-08-09 
 * @function   :Setting the display direction of LCD screen
 * @parameters :direction:0-0 degree
                          1-90 degree
													2-180 degree
													3-270 degree
 * @retvalue   :None
******************************************************************************/ 
void LCD_direction(u8 direction)
{ 
			lcddev.setxcmd=0x2A;
			lcddev.setycmd=0x2B;
			lcddev.wramcmd=0x2C;
	switch(direction){		  
		case 0:						 	 		
			lcddev.width=LCD_W;
			lcddev.height=LCD_H;		
			LCD_WriteReg(0x36,(0<<3)|(1<<6)|(1<<7));//BGR==1,MY==0,MX==0,MV==0
		break;
		case 1:
			lcddev.width=LCD_H;
			lcddev.height=LCD_W;
			LCD_WriteReg(0x36,(0<<3)|(1<<7)|(1<<5));//BGR==1,MY==1,MX==0,MV==1
		break;
		case 2:						 	 		
			lcddev.width=LCD_W;
			lcddev.height=LCD_H;	
			LCD_WriteReg(0x36,(0<<3)|(0<<6)|(0<<7));//BGR==1,MY==0,MX==0,MV==0
		break;
		case 3:
			lcddev.width=LCD_H;
			lcddev.height=LCD_W;
			LCD_WriteReg(0x36,(0<<3)|(0<<7)|(1<<6)|(1<<5));//BGR==1,MY==1,MX==0,MV==1
		break;	
		default:break;
	}		
}	 
#ifndef _SPI_LCD_H_
#define _SPI_LCD_H_
	
#include "main.h"	 
#include "stdlib.h"
#include "gpio.h"

#define u32 unsigned  int
#define u16 unsigned short
#define u8 unsigned char
	
//液晶控制口置1操作语句宏定义

#define	SPI_MOSI_SET  	 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET);    
#define	SPI_SCLK_SET  	 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); 


//液晶控制口置0操作语句宏定义

#define	SPI_MOSI_CLR  	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET);   
#define	SPI_SCLK_CLR  	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);  


void  SPIv_WriteData(unsigned char Data);



//LCD重要参数集
typedef struct  
{										    
	u16 width;			//LCD 宽度
	u16 height;			//LCD 高度
	u16 id;				  //LCD ID
	u8  dir;			  //横屏还是竖屏控制:0,竖屏;1,横屏。	
	u16	 wramcmd;		//开始写gram指令
	u16  setxcmd;		//设置x坐标指令
	u16  setycmd;		//设置y坐标指令	 
}_lcd_dev; 	

//LCD参数
extern _lcd_dev lcddev;	//管理LCD重要参数
/用户配置区///	 
#define USE_HORIZONTAL  	 0//定义液晶屏顺时针旋转方向 	0-0度旋转,1-90度旋转,2-180度旋转,3-270度旋转

//	  
//定义LCD的尺寸
#define LCD_W 128
#define LCD_H 160

//TFTLCD部分外要调用的函数		   
extern u16  POINT_COLOR;//默认红色    
extern u16  BACK_COLOR; //背景颜色.默认为白色


//-----------------  LCD端口定义直接不需要了,只需要在STM32CubeMX上设置好IO口并且标签打好,直接连接就能用  ---------------- 
#define	LCD_BLK_SET	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
 //LCD背光打开,QDtech全系列模块采用了三极管控制背光亮灭,用户也可以接PWM调节背光亮度
//如果使用官方库函数定义下列底层,速度将会下降到14帧每秒,建议采用他们公司推荐方法
//以下IO定义直接操作寄存器,快速IO操作,刷屏速率可以达到28帧每秒! 


//GPIO功能口置位(拉高)
#define	LCD_CS_SET   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);  
#define	LCD_RS_SET	 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);     //数据/命令     (DC RS 指的是同一个引脚哈) 
#define	LCD_RST_SET	 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);    //复位			 
//GPIO功能口复位(拉低)							    
#define	LCD_CS_CLR  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);  
#define	LCD_RS_CLR	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);      //数据/命令  
#define	LCD_RST_CLR	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);    //复位			


//画笔颜色
#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 //灰色
//GUI颜色

#define DARKBLUE      	 0X01CF	//深蓝色
#define LIGHTBLUE      	 0X7D7C	//浅蓝色  
#define GRAYBLUE       	 0X5458 //灰蓝色
//以上三色为PANEL的颜色 
 
#define LIGHTGREEN     	0X841F //浅绿色
#define LIGHTGRAY     0XEF5B //浅灰色(PANNEL)
#define LGRAY 			 		0XC618 //浅灰色(PANNEL),窗体背景色

#define LGRAYBLUE      	0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE          0X2B12 //浅棕蓝色(选择条目的反色)

void  SPIv_WriteData(u8 Data);
void LCD_WR_REG(u8 data);
void LCD_WR_DATA(u8 data);
void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue);
void LCD_WriteRAM_Prepare(void);
void Lcd_WriteData_16Bit(u16 Data);
void LCD_DrawPoint(u16 x,u16 y);
void LCD_Clear(u16 Color);
void LCD_RESET(void);
void LCD_Init(void);
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd);
void LCD_SetCursor(u16 Xpos, u16 Ypos);
void LCD_direction(u8 direction);
	 

#endif

第一个C文件没什么好说的,就是根据通讯时序写的,自己可以练习写一写通讯时序,作为小白的我就直接白嫖了哈哈哈哈。第二个H文件,里面对引脚的一些宏定义,要注意根据自己设定的修改,相应的拉高或者拉低电平,要记得背光引脚电平拉高,不信的小伙伴可以试一试。

LCD显示函数就没有什么好说的了,直接用就行。
接下来介绍两个好用的函数,画网格和lcd显示波形。
1.画网格

/*****************************************************************************
**自己编写的函数

名称:void LCD_Drawgrid(int wid,int lcd_wid,int lcd_high)
功能:画网格
参数:网格宽度,lcd屏幕宽度,LCD屏幕高度
******************************************************************************/ 
void LCD_Drawgrid(int wid,int lcd_wid,int lcd_high)
		{
			float row,col;
			int nrow,ncol;
			lcd_wid = 128;
			lcd_high = 160;
			row = (float)lcd_wid/wid;
			col = (float)lcd_high/wid;
			nrow = (int)lcd_wid/wid;
			ncol = (int)lcd_high/wid;
			if(row>nrow)
				nrow = nrow + 1;
			if(row==nrow)
				nrow = nrow;
			if(col>ncol)
				ncol = ncol + 1;
			if(col==ncol)
				ncol = ncol;
			for(int i = 0; i <ncol; i++)
			{
				for(int j = 0; j <nrow; j++)
				{
						LCD_DrawLine(0,i*wid,lcd_wid,i*wid);
						LCD_DrawLine(j*wid,0,j*wid,lcd_high);
				}
			}
		}

2.显示波形

/*****************************************************************************
名称:void drawCurve(short int rawValue)  
功能:画波形
参数:波形数据
注意:	uint16_t lastX,lastY;            移植前别忘记定义这两
			unsigned char firstPoint = 1;
******************************************************************************/ 
uint16_t lastX,lastY;
unsigned char firstPoint = 1;
void drawCurve(short int rawValue)  
{
	uint16_t x,y;
	y = 100-rawValue/100;  	//起始坐标y的值,改变函数幅值
	//这里之所以是120-rawValue/280,与屏幕的扫描方向有关,如果出现上下颠倒的情况,可以改成120 + 
	if(firstPoint)//如果是第一次画点,则无需连线,直接描点即可
	{
		LCD_DrawPoint(0,y);
		lastX=0;
		lastY=y;
		firstPoint=0;
	}
	else
	{
		x=lastX+1;
		if(x<160)  //不超过屏幕宽度
		{
			LCD_DrawLine(lastY,lastX,y,x);
			HAL_Delay(20);
			lastX=x;
			lastY=y;
		}
		else  //超出屏幕宽度,清屏,从第一个点开始绘制,实现动态更新效果
		{
			LCD_Clear(WHITE);//清屏,白色背景
			LCD_Drawgrid(20,128,160);
			HAL_Delay(300);
			LCD_DrawPoint(0,y);
			lastX=0;
			lastY=y;
		}
  }
}

第二个函数是csdn上另外一位博主的,链接忘记了
它可以根据数据显示波形,最好把数据放在一个数组里面,然后用for循环取出来,

int a[100] = {2112,2241,2368,2495,2619,2742,2861,2978,3091,3199,3303,3402,3496,3584,3666,3742,3811,
3873,3928,3975,4015,4047,4071,4087,4095,4095,4087,4071,4047,4015,3975,3928,3873,
3811,3742,3666,3584,3496,3402,3303,3199,3091,2978,2861,2742,2619,2495,2368,2241,
2112,1984,1855,1728,1601,1477,1354,1235,1118,1005,897,793,694,600,512,430,
354,285,223,168,121,81,49,25,9,1,1,9,25,49,81,121,
168,223,285,354,430,512,600,694,793,897,1005,1118,1235,1354,1477,1601,
1728,1855,1984,};

可以用这组数据测试。
在这里插入图片描述
放在while(1)里面。

分享一下淘宝的例程资料下载:https://pan.baidu.com/s/1bp6AYsR
下面是我的代码
代码
分享结束,欢迎指正

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于cubemx的stm32HAL库SPI通信写LCD显示屏 的相关文章

  • js连接web3,连接小狐狸metamask钱包,实现链不对后切换网络和创建网络

    直接上代码 我这里吧所有配置都改成正式的链56 一旦用户的小狐狸钱包现在的链不一致 就询问切换网络 没有就创建网络 网络切换成功后 收到监听 重新连接一下web3 就是重新调用一些connectWeb3这个方法 再连接合约 connectW
  • 20230918使用ffmpeg将mka的音频转为AAC编码以便PR2023来识别

    20230918使用ffmpeg将mka的音频转为AAC编码以便PR2023来识别 2023 9 18 20 58 ffmpeg i 1 mka acodec aac 1 mp4 ffmpeg i 1 mka vn c a aac 2 aa
  • MYSQL  Replication  主从配置

    MYSQL Replication 主从配置 MySQL Replication 又叫做AB复制或者主从复制 它主要用于MySQL的实时备份或者读写分离 在配置之前先做一下准备工作 配置两台mysql服务器 或者在一台服务器上配置两个端口也
  • IAR for AVR中的位定义使用

    目的 打开IAR for AVR中的位定义 在单片机的编程中 经常会遇到 UCSRB 1 lt lt TXEN 这样的表达式 查看定义可以在头文件中看到 define TXEN 3 表示的是 1 lt lt TXEN 是将1左移3位 然后赋
  • 使用 pandas 导出数据

    import pandas as pd In 58 df pd DataFrame houselist In 59 df In 61 df to csv lianjia 转载于 https www cnblogs com polly lin
  • 字符串 反转

    LC 反转字符串 swift 实现 var s Character h e l l o reversString s print s func reversString s inout Character var temp Characte

随机推荐

  • SQLServer 数据 迁移转到Mysql 中

    目录 一 SQLServer 转Mysql 的几种方法 二 DB2DB 使用 2 1 迁移出错后的报错日志 三 补齐出现问题的表 问题 原因 解决 一 SQLServer 转Mysql 的几种方法 sqlServer 转mysql 最大的问
  • vue3(二)配置标题和服务代理

    这里的标题如何改成自己的标题 第一步 修改vue config js transpileDependencies true chainWebpack config gt config plugin html tap args gt args
  • android广播数据大小限制,android 限制广播消息的接收者

    原文 http blog csdn net mingli198611 article details 17762149 在android系统中sendBroadcast和BroadcastReceiver 只要BroadcastReceiv
  • Linux学习(未完待续。。。)

    安装好ubuntu 并且注册用户成功后 给root设置密码 sudo passwd root 先输入自己的密码 然后输入root的密码 再确认 密码都是不可见的 不是键盘坏了 显示日期格式 date Y m d H M S m month
  • Hyperledger Fabric学习笔记——7.链码安装、实例化、执行

    1 智能合约 执行环境 以太坊虚拟智能合约执行环境EVM fabric执行环境是docker 链码 是应用层和区块链底层的中间点 每一个链码执行环境是一个独立的docker 使用GRPC协议与背书节点通信 只有背书节点才能运行智能合约 链码
  • 如何配置服务器自动监控并报警

    作者 一个懂技术的运营 链接 https www zhihu com question 21073555 answer 106131463 来源 知乎 著作权归作者所有 商业转载请联系作者获得授权 非商业转载请注明出处 如果是初创型公司 机
  • Vue 的forEach和push

    tagTacticsFilter tacticsTag let data let tacticsTagList this tacticsTagList let attrList tacticsTag split attrList forEa
  • 真正的学懂三极管入门篇(经典)

    不要让温床称为埋葬你的坟墓 要有危机意识 忧患意识 要为明天考虑 禁忌 安于现状 不求上进 不懂得学习 不能恰当的处理工作和学习关系 没有把英语放在第一位
  • uniApp中 nvue和vue开发 小结

    最近接手uniapp开发 对遇到的问题进行总结 什么是nvue nvue native vue 原生渲染 为何要用nvue开发 weex 有个很大的问题是它只是一个高性能的渲染器 没有足够的API能力 比如各种push sdk集成 蓝牙等能
  • 电梯调度算法-C++

    1 算法解析 扫描算法 SCAN 又称电梯调度算法 SCAN算法是磁头前进方向上的最短查找时间优先算法 它排除了磁头在盘面局部位置上的往复移动 SCAN算法在很大程度上消除了SSTF算法的不公平性 但仍有利于对中间磁道的请求 电梯调度算法是
  • 【图解】ThreadLocal底层实现原理

    1 ThreadLocal的底层原理图 说明 Thread中有threadLocals成员变量 threadLocal会在threadlocal首次set时进行赋值 这会在非main线程中复现 主线程启动即会进行赋值 ThreadLocal
  • git使用(由浅到深)

    目录流程图 1 分布式版本控制与集中式版本控制 1 1 集中式版本控制 集中式版本控制系统有 CVS和SVN 它们的主要特点是单一的集中管理的服务器 保存所有文件的修订版本 协同开发人员通过客户端连接到这台服务器 取出最新的文件或者提交更新
  • Java面试题及答案整理(2021最新版)

    Java面试题及答案整理 一 Java 基础 1 JDK 和 JRE 有什么区别 2 和 equals 的区别是什么 3 两个对象的 hashCode 相同 则 equals 也一定为 true 对吗 4 final 在 java 中有什么
  • C语言中C89与C99的区别

    1 增加restrict指针 C99中增加了公适用于指针的restrict类型修饰符 它是初始访问指针所指对象的惟一途径 因此只 有借助restrict指针表达式才能访问对象 restrict指针指针主要用做函数变元 或者指向由malloc
  • QT中json与数据转换

    QT中json与数据转换 一 json简介 二 json文件的写入与解析 1 简单的json对象 2 json数组 3 复杂的json对象 三 QT中配置文件应用json实现 1 需求 2 打开工程 3 保存工程 4 新建工程 一 json
  • java无法从静态上下文_ERROR无法从静态上下文中引用非静态变量

    什么是 static 学习过java C 或C的人都应该认识这个关键字 用这个关键字修饰的变量叫做静态变量 有其特殊的作用 在java中static也用来修饰静态方法和静态内部类 静态变量的特点 1 生存周期 静态局部变量的生存周期也是整个
  • 华为华三思科 配置arp IP地址和mac地址绑定

    华为
  • 微信小程序存在的风险_警惕,你的微信小程序可能面临着风险!

    小程序目前在移动互联网领域的流行 它有火 到6月底的数据告诉你 微信微型节目C端用户达到2 8亿 迷你程序达到100万 累计用户数达到6亿 即时访问 不需要下载 成为用户使用小程序的触发点 但在建立生态的小程序 其独特的安全风险也逐渐显示出
  • 四千个厂商默认账号密码 默认登录凭证

    Product Vendor Username Password Zyxel ssh zyfwp PrOw aN fXp APC UPS web apc apc Weblogic web system manager Weblogic we
  • 基于cubemx的stm32HAL库SPI通信写LCD显示屏

    之前学习了如何使用LCD 记录一下 关于spi部分是从野火的资料中截取 也会加入我自己的备注 便于理解 代码部分在后面 请耐心看完 一 SPI协议简介 SPI 协议是由摩托罗拉公司提出的通讯协议 Serial Peripheral Inte