CW_SPI配置
首先可以很方便的从手册上看见CW32的SPI引脚
我用的是非触摸的屏幕 所以只配置使用了SCK(时钟引脚)和MOSI(主机输出从机输入)
从手册上可以看到单工单发/主机模式下,MOSI和SCK引脚需配置为数字/推挽输出/复用
这里就贴一下SPI的配置代码
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_TxOnly; //单工只发
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主机模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //八位数据
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //时钟极性-默认高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //时钟触发模式 第二个边沿开始
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //软件片选
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;//fspi = 64MHz/4 = 16MHz
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//高位在前
SPI_InitStructure.SPI_Speed = SPI_Speed_Low; //低速模式
SPI_Init(CW_SPI2, &SPI_InitStructure);
SPI_Cmd(CW_SPI2, ENABLE);
LCD配置
上面讲到了SPI的配置,下面就该讲讲屏幕使用到的引脚以及初始化了
首先,屏幕有8个引脚,他们分别为 GND VCC SCL SDA RES DC CS BL
GND/VCC:电源正负极
SCL:时钟引脚,接CW32的SPI_SCK 即PA02
SDA:数据输入引脚,接CW32的SPI_MOSI 即 PA01
RES:屏幕复位引脚,低电平复位 接PA03
DC:数据/命令选择引脚,低电平发送命令,高电平发送数据 接PA04
CS:片选信号,低电平选中 接PA05(使用的软件片选)
BL:背光引脚,用于控制屏幕亮度 接PA06
使用到的引脚都是GPIOA端口且都是推挽输出,所以初始化代码如下
PA01_AFx_SPI2MOSI(); //引脚复用
PA02_AFx_SPI2SCK(); //引脚复用
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Pins = LSCL|LSDA|LRES|LDC|LCS|LBL;
GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
然后就是LCD初始化配置了(可以在屏幕的数据手册上找到),太长了,所以一会放最下面。
这里补充一下SPI的写函数
void LCD_WriteCmd(uint8_t cmd)
{
LCS_CLR; //开始通信
LDC_CLR; //指令
SPI_SendData(CW_SPI2, cmd);
while(!SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE));//等待本次发送完成
LCS_SET; //结束通信
}
void LCD_WriteData(uint8_t data)
{
LCS_CLR; //开始通信
LDC_SET; //数据
SPI_SendData(CW_SPI2, data);
while(!SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE));//等待本次发送完成
LCS_SET; //结束通信
}
void LCD_Write2Byte(uint16_t data)
{
LCS_CLR; //开始通信
LDC_SET; //数据
SPI_SendData(CW_SPI2, (uint8_t)(data>>8));
while(SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE) == RESET);//等待本次发送完成
SPI_SendData(CW_SPI2, (uint8_t)data);
while(SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE) == RESET);//等待本次发送完成
LCS_SET; //结束通信
}
最后贴一下所有代码
LCD.C
#include "lcd.h"
#include "font.h"
#include "math.h"
void LCD_Delay(void)
{
uint16_t i = 0xfff;
while(i--);
}
void LCD_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
__RCC_SPI2_CLK_ENABLE();
__RCC_GPIOA_CLK_ENABLE();
PA01_AFx_SPI2MOSI();
PA02_AFx_SPI2SCK();
//将 SPIx_SCK、SPIx_MOSI 和 SPIx_CS 配置为推挽复用输出模式
//SPIx_MISO 引脚配置为浮空输入、复用模式
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Pins = LSCL|LSDA|LRES|LDC|LCS|LBL;
GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_TxOnly; //单工只发
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主机模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //八位数据
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //时钟极性-默认高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //时钟触发模式 第二个边沿开始
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //软件片选
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;//fspi = 64MHz/4 = 16MHz
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//高位在前
SPI_InitStructure.SPI_Speed = SPI_Speed_Low; //低速模式
SPI_Init(CW_SPI2, &SPI_InitStructure);
SPI_Cmd(CW_SPI2, ENABLE);
LCS_SET; //片选失能
LBL_SET; //打开背光
LDC_SET;
}
void LCD_Rest()
{
LRES_CLR;
LCD_Delay();
LRES_SET;
LCD_Delay();
}
void LCD_WriteCmd(uint8_t cmd)
{
LCS_CLR; //开始通信
LDC_CLR; //指令
SPI_SendData(CW_SPI2, cmd);
while(!SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE));//等待本次发送完成
LCS_SET; //结束通信
}
void LCD_WriteData(uint8_t data)
{
LCS_CLR; //开始通信
LDC_SET; //数据
SPI_SendData(CW_SPI2, data);
while(!SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE));//等待本次发送完成
LCS_SET; //结束通信
}
void LCD_Write2Byte(uint16_t data)
{
LCS_CLR; //开始通信
LDC_SET; //数据
SPI_SendData(CW_SPI2, (uint8_t)(data>>8));
while(SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE) == RESET);//等待本次发送完成
SPI_SendData(CW_SPI2, (uint8_t)data);
while(SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE) == RESET);//等待本次发送完成
LCS_SET; //结束通信
}
void LCD_Init(void)
{
LCD_Config();
LCD_Rest();
LCD_WriteCmd(0x11);//Sleep exit
LCD_WriteCmd(0xB1);
LCD_WriteData(0x01);
LCD_WriteData(0x2C);
LCD_WriteData(0x2D);
LCD_WriteCmd(0xB2);
LCD_WriteData(0x01);
LCD_WriteData(0x2C);
LCD_WriteData(0x2D);
LCD_WriteCmd(0xB3);
LCD_WriteData(0x01);
LCD_WriteData(0x2C);
LCD_WriteData(0x2D);
LCD_WriteData(0x01);
LCD_WriteData(0x2C);
LCD_WriteData(0x2D);
LCD_WriteCmd(0xB4); //Column inversion
LCD_WriteData(0x07);
LCD_WriteCmd(0xC0);
LCD_WriteData(0xA2);
LCD_WriteData(0x02);
LCD_WriteData(0x84);
LCD_WriteCmd(0xC1);
LCD_WriteData(0xC5);
LCD_WriteCmd(0xC2);
LCD_WriteData(0x0A);
LCD_WriteData(0x00);
LCD_WriteCmd(0xC3);
LCD_WriteData(0x8A);
LCD_WriteData(0x2A);
LCD_WriteCmd(0xC4);
LCD_WriteData(0x8A);
LCD_WriteData(0xEE);
LCD_WriteCmd(0xC5); //VCOM
LCD_WriteData(0x0E);
LCD_WriteCmd(0x36); //MX, MY, RGB mode
LCD_WriteData(0xC8);
LCD_WriteCmd(0xe0);
LCD_WriteData(0x0f);
LCD_WriteData(0x1a);
LCD_WriteData(0x0f);
LCD_WriteData(0x18);
LCD_WriteData(0x2f);
LCD_WriteData(0x28);
LCD_WriteData(0x20);
LCD_WriteData(0x22);
LCD_WriteData(0x1f);
LCD_WriteData(0x1b);
LCD_WriteData(0x23);
LCD_WriteData(0x37);
LCD_WriteData(0x00);
LCD_WriteData(0x07);
LCD_WriteData(0x02);
LCD_WriteData(0x10);
LCD_WriteCmd(0xe1);
LCD_WriteData(0x0f);
LCD_WriteData(0x1b);
LCD_WriteData(0x0f);
LCD_WriteData(0x17);
LCD_WriteData(0x33);
LCD_WriteData(0x2c);
LCD_WriteData(0x29);
LCD_WriteData(0x2e);
LCD_WriteData(0x30);
LCD_WriteData(0x30);
LCD_WriteData(0x39);
LCD_WriteData(0x3f);
LCD_WriteData(0x00);
LCD_WriteData(0x07);
LCD_WriteData(0x03);
LCD_WriteData(0x10);
LCD_WriteCmd(0x2a);
LCD_WriteData(0x00);
LCD_WriteData(0x00);
LCD_WriteData(0x00);
LCD_WriteData(0x7f);
LCD_WriteCmd(0x2b);
LCD_WriteData(0x00);
LCD_WriteData(0x00);
LCD_WriteData(0x00);
LCD_WriteData(0x9f);
LCD_WriteCmd(0xF0); //Enable test command
LCD_WriteData(0x01);
LCD_WriteCmd(0xF6); //Disable ram power save mode
LCD_WriteData(0x00);
LCD_WriteCmd(0x3A); //65k mode
LCD_WriteData(0x05);
LCD_WriteCmd(0x29);//Display on
LCD_Clear(BLACK);
}
//设置写入范围
void setRegion(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1 )
{
LCD_WriteCmd(0x2a);
LCD_Write2Byte(x0+2);
LCD_Write2Byte(x1+2);
// Y轴
LCD_WriteCmd(0x2b);
LCD_Write2Byte(y0+3);
LCD_Write2Byte(y1+3);
// 写入命令
LCD_WriteCmd(0x2c);
}
//设置光标位置
void setPoint(uint8_t x, uint8_t y)
{
LCD_WriteCmd(0x2a);
LCD_Write2Byte(x+2);
// Y轴
LCD_WriteCmd(0x2b);
LCD_Write2Byte(y+3);
// 写入命令
LCD_WriteCmd(0x2c);
}
void LCD_Clear( uint16_t color )
{
uint16_t area = MAX_H * MAX_W;
setRegion(0,0,MAX_W - 1,MAX_H - 1);
while(area--) LCD_Write2Byte(color);
}
void LCD_ClearPart(uint8_t x0,uint8_t y0, uint8_t x1,uint8_t y1, uint16_t color )
{
uint16_t area = (y1 - y0) * (x1 - x0);
setRegion(x0,y0,x1,y1);
while(area--) LCD_Write2Byte(color);
}
void LCD_DrawPoint(uint8_t x, uint8_t y, uint16_t color)
{
setPoint(x,y);
LCD_Write2Byte(color);
}
/**************************************
函数名:LCD_ShowChar
函数作用:显示一个字符(无背景色)
参数:x/y->显示坐标
size->字符大小 6/8/12 分别对应 6*12/8*16/12*24
color->颜色 0x0000-0xffff
ch->需要显示的字符
注意:字符类型取列行式
**************************************/
void LCD_ShowChar(uint8_t x, uint8_t y, uint8_t size, uint16_t color, uint8_t chr)
{
uint8_t i,j,n;
uint8_t N = (size + 3) / 4; //获取一个字符对应的高度
for(n=0; n<N; n++)
{
for(j=0;j<size;j++)
{
for(i=0;i<8;i++)
{
if(size == 6)
{
if((0x01<<i)&F6x12[chr - ' '][n*size+j]) LCD_DrawPoint(x+j,y+n*8+i,color);
}
else if(size == 8)
{
if((0x01<<i)&F8x16[chr - ' '][n*size+j]) LCD_DrawPoint(x+j,y+n*8+i,color);
}
else if(size == 12)
{
if((0x01<<i)&F12x24[chr - ' '][n*size+j]) LCD_DrawPoint(x+j,y+n*8+i,color);
}
}
}
}
}
void LCD_ShowStr(uint8_t x, uint8_t y, uint8_t size, uint16_t color,uint8_t *str)
{
uint8_t i;
for(i=0; str != '\0'; i++)
{
LCD_ShowChar(x,y,size,color,str);
x += size;
if((x + size) > MAX_W)
{
x = 0;
y += 2 * size;
}
}
}
/**************************************
函数名:LCD_ShowChar
函数作用:显示一个字符(带背景色)
参数:x/y->显示坐标
size->字符大小 6/8/12 分别对应 6*12/8*16/12*24
color->颜色 0x0000-0xffff
ch->需要显示的字符
注意:字符类型取列行式
**************************************/
void LCD_ShowBChar(uint8_t x, uint8_t y, uint8_t size, uint16_t color,uint16_t BackColor, uint8_t chr)
{
uint8_t i,j,n;
uint8_t N = (size + 3) / 4; //获取一个字符对应的高度
for(n=0; n<N; n++)
{
for(j=0;j<size;j++)
{
for(i=0;i<8;i++)
{
if(size == 6)
{
if((0x01<<i)&F6x12[chr - ' '][n*size+j]) LCD_DrawPoint(x+j,y+n*8+i,color);
else LCD_DrawPoint(x+j,y+n*8+i,BackColor);
}
else if(size == 8)
{
if((0x01<<i)&F8x16[chr - ' '][n*size+j]) LCD_DrawPoint(x+j,y+n*8+i,color);
else LCD_DrawPoint(x+j,y+n*8+i,BackColor);
}
else if(size == 12)
{
if((0x01<<i)&F12x24[chr - ' '][n*size+j]) LCD_DrawPoint(x+j,y+n*8+i,color);
else LCD_DrawPoint(x+j,y+n*8+i,BackColor);
}
}
}
}
}
void LCD_ShowBStr(uint8_t x, uint8_t y, uint8_t size, uint16_t color,uint16_t BackColor,uint8_t *str)
{
uint8_t i;
for(i=0; str != '\0'; i++)
{
LCD_ShowBChar(x,y,size,color, BackColor,str);
x += size;
if((x + size) > MAX_W)
{
x = 0;
y += 2 * size;
}
}
}
void LCD_ShowBMP(uint8_t x, uint8_t y,uint8_t w, uint8_t h, const uint8_t bmp[], uint16_t color)
{
uint8_t i,j,n,N;
N = h/8;
if(h%8 != 0) N += 1;
for(n=0;n<N;n++)
{
for(j=0;j<w;j++)
{
for(i=0;i<8;i++)
{
if((bmp[n*w+j] >> i) & 0x01) LCD_DrawPoint(x+j,y+i,color);
}
}
y += 8;
}
}
void LCD_DrawLine(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1,uint16_t color)
{
int dx, // difference in x's
dy, // difference in y's
dx2, // dx,dy * 2
dy2,
x_inc, // amount in pixel space to move during drawing
y_inc, // amount in pixel space to move during drawing
error, // the discriminant i.e. error i.e. decision variable
index; // used for looping
setPoint(x0,y0);
dx = x1-x0;//计算x距离
dy = y1-y0;//计算y距离
if (dx>=0)
{
x_inc = 1;
}
else
{
x_inc = -1;
dx = -dx;
}
if (dy>=0)
{
y_inc = 1;
}
else
{
y_inc = -1;
dy = -dy;
}
dx2 = dx << 1;
dy2 = dy << 1;
if (dx > dy)
{
error = dy2 - dx;
for (index=0; index <= dx; index++)
{
LCD_DrawPoint(x0,y0,color);
if (error >= 0)
{
error-=dx2;
y0+=y_inc;
}
error+=dy2;
x0+=x_inc;
}
}
else
{
error = dx2 - dy;
for (index=0; index <= dy; index++)
{
LCD_DrawPoint(x0,y0,color);
if (error >= 0)
{
error-=dy2;
x0+=x_inc;
}
error+=dx2;
y0+=y_inc;
}
}
}
void LCD_DrawCricle(uint8_t x,uint8_t y,uint8_t r,uint16_t color)
{
int dy,dx;
dx=r;
dy=0;
while(dy<r)
{
if(dx>=dy)
{
LCD_DrawPoint(x+dx,y-dy,color);
LCD_DrawPoint(x-dx,y-dy,color);
LCD_DrawPoint(x+dx,y+dy,color);
LCD_DrawPoint(x-dx,y+dy,color);
LCD_DrawPoint(y+dy,y-dx,color);
LCD_DrawPoint(y-dy,y-dx,color);
LCD_DrawPoint(y+dy,y+dx,color);
LCD_DrawPoint(y-dy,y+dx,color);
}
dy++;
dx=sqrt((double)r*r-dy*dy);
}
}
void LCD_FullCircle(uint8_t x, uint8_t y, uint8_t r, uint16_t color)
{
uint16_t dx,dy,dr=r;
for(dy=y - dr;dy<y +dr;dy++)
{
for(dx=x - dr;dx<x+dr;dx++)
{
if(((dx-x)*(dx-x)+(dy-y)*(dy-y)) <= dr*dr)
{
LCD_DrawPoint(dx,dy,color);
}
}
}
}
下面是LCD.h文件
#ifndef __LCD_H
#define __LCD_H
#include "cw32f030.h"
#include "cw32f030.h"
#include "cw32f030_spi.h"
#include "cw32f030_gpio.h"
#include "cw32f030_rcc.h"
#define RED 0xf800
#define GREEN 0x07e0
#define BLUE 0x001f
#define YELLOW 0xffe0
#define BLACK 0x0000
#define WHITE 0xffff
#define MAX_W 128
#define MAX_H 128
//CW_SPI2
#define LSCL GPIO_PIN_2
#define LSDA GPIO_PIN_1
#define LRES GPIO_PIN_3
#define LDC GPIO_PIN_4
#define LCS GPIO_PIN_5
#define LBL GPIO_PIN_6
#define LCS_SET CW_GPIOA->BSRR = LCS
#define LCS_CLR CW_GPIOA->BRR = LCS
#define LDC_SET CW_GPIOA->BSRR = LDC
#define LDC_CLR CW_GPIOA->BRR = LDC
#define LRES_SET CW_GPIOA->BSRR = LRES
#define LRES_CLR CW_GPIOA->BRR = LRES
#define LBL_SET CW_GPIOA->BSRR = LBL
#define LBL_CLR CW_GPIOA->BRR = LBL
void LCD_Init(void ); // LCD初始化
void LCD_Clear(uint16_t color ) ;
void LCD_ClearPart(uint8_t x0,uint8_t y0, uint8_t x1,uint8_t y1, uint16_t color );
void LCD_ShowChar(uint8_t x, uint8_t y, uint8_t size, uint16_t color,uint8_t chr);
void LCD_ShowBChar(uint8_t x, uint8_t y, uint8_t size, uint16_t color,uint16_t BackColor, uint8_t chr);
void LCD_ShowStr(uint8_t x, uint8_t y, uint8_t size, uint16_t color, uint8_t *str);
void LCD_ShowBStr(uint8_t x, uint8_t y, uint8_t size, uint16_t color,uint16_t BackColor,uint8_t *str) ;
void LCD_ShowBMP(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t bmp[], uint16_t color);
void LCD_DrawLine(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1,uint16_t color);
void LCD_DrawPoint(uint8_t x, uint8_t y, uint16_t color);
void LCD_DrawCricle(uint8_t x,uint8_t y,uint8_t r,uint16_t color);
void LCD_FullCircle(uint8_t x,uint8_t y,uint8_t r,uint16_t color);
void LCD_DrawCurve(uint32_t* data,uint8_t x);
#endif
我觉得font.h就没必要补充了
自己取字模的时候注意一下配置就行(列行式,C51格式)
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_45813999/article/details/131538800
|
 共1人点赞
|