最近在项目上用到LCD屏,屏幕大小为128*64,芯片为ST7565不带字库的
STM32F103代码实现,用的是ST的LL库
#define CS_Pin LL_GPIO_PIN_5
#define CS_GPIO_Port GPIOB
#define RST_Pin LL_GPIO_PIN_6
#define RST_GPIO_Port GPIOB
#define A0_Pin LL_GPIO_PIN_8
#define A0_GPIO_Port GPIOB
#define OLED_CS_HIGH() LL_GPIO_SetOutputPin(CS_GPIO_Port,CS_Pin)
#define OLED_CS_LOW() LL_GPIO_ResetOutputPin(CS_GPIO_Port,CS_Pin)
#define OLED_WDATA() LL_GPIO_SetOutputPin(A1_GPIO_Port,A1_Pin)
#define OLED_WCMD() LL_GPIO_ResetOutputPin(A1_GPIO_Port,A1_Pin)
//IO口初始化
static void MX_GPIO_Init(void)
{
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOC);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOD);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
/**/
LL_GPIO_ResetOutputPin(GPIOB, CS_Pin|RST_Pin|A0_Pin);
/**/
GPIO_InitStruct.Pin = CS_Pin|RST_Pin|A0_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
//spi2初始化
static void MX_SPI2_Init(void)
{
/* USER CODE BEGIN SPI2_Init 0 */
/* USER CODE END SPI2_Init 0 */
LL_SPI_InitTypeDef SPI_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
/**SPI2 GPIO Configuration
PB13 ------> SPI2_SCK
PB15 ------> SPI2_MOSI
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_13|LL_GPIO_PIN_15;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* SPI2 interrupt Init */
NVIC_SetPriority(SPI2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_DisableIRQ(SPI2_IRQn);
/* USER CODE BEGIN SPI2_Init 1 */
/* USER CODE END SPI2_Init 1 */
/* SPI2 parameter configuration*/
SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV64;
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI_InitStruct.CRCPoly = 10;
LL_SPI_Init(SPI2, &SPI_InitStruct);
/* USER CODE BEGIN SPI2_Init 2 */
LL_SPI_EnableIT_TXE(SPI2);
LL_SPI_Enable(SPI2);
/* USER CODE END SPI2_Init 2 */
}
//写命令
void SpiWriteComd(uint8_t val)
{
OLED_WCMD();
OLED_CS_LOW();
LL_SPI_TransmitData8(SPI2, val);
while(LL_SPI_IsActiveFlag_TXE(SPI2) == 0);
while(LL_SPI_IsActiveFlag_BSY(SPI2) == 1); //等待发送完成后,置高CS,不能早不能晚
OLED_CS_HIGH();
}
//写数据
void SpiWriteData(uint8_t val)
{
OLED_WDATA();
OLED_CS_LOW();
LL_SPI_TransmitData8(SPI2, val);
while(LL_SPI_IsActiveFlag_TXE(SPI2) == 0);
while(LL_SPI_IsActiveFlag_BSY(SPI2) == 1); //等待发送完成后,置高CS,不能早不能晚
OLED_CS_HIGH();
}
//延时
void Lcd_DelayUs(uint32_t us)
{
uint8_t i;
while(--us>0){
for(i=0; i<10; ++i){
//asm("NOP");
LL_IWDG_ReloadCounter(IWDG);
}
}
}
//复位
void Lcd_Reset(void)
{
LL_GPIO_ResetOutputPin(RST_GPIO_Port, RST_Pin);
Lcd_DelayUs(1000);
LL_GPIO_SetOutputPin(RST_GPIO_Port, RST_Pin);
}
//清屏
void Clear(void)
{
uint8_t i,j;
for(i=0;i<8;i++)
{
SpiWriteComd(0xb0 + i);
SpiWriteComd(0x10);
SpiWriteComd(0);
for(j=0;j<128;j++)
{
SpiWriteData(0x00);
}
}
}
//设置行
void SetLine(uint8_t line)
{
line = line & 0x07;
line = line | 0xB0;
SpiWriteComd(line);
}
//设置列
void SetColumn(uint8_t col)
{
uint8_t col_h,col_l;
col = col & 0x7F;
col_h = col & 0xF0;
col_h >>= 4;
col_h |= 0x10;
col_l = col & 0x0F;
col_l |= 0x00;
SpiWriteComd(col_h);
SpiWriteComd(col_l);
}
//写汉字
void PutChinese(uint8_t line,uint8_t column,const uint8_t * data)
{
uint32_t j;
SetLine(line);
SetColumn(column);
for(j=0;j<16;j++)
{
SpiWriteData(*data++);
}
SetLine(line + 1);
SetColumn(column);
for(j=0;j<16;j++)
{
SpiWriteData(*data++);
}
}
//写字符
void PutAscii(uint8_t line,uint8_t column,const uint8_t * data)
{
uint32_t j;
SetLine(line);
SetColumn(column);
for(j=0;j<8;j++)
{
SpiWriteData(*data++);
}
SetLine(line + 1);
SetColumn(column);
for(j=0;j<8;j++)
{
SpiWriteData(*data++);
}
}
//初始化
void InitDisplay(void)
{
uint32_t i;
Lcd_Reset();
Clear();
SpiWriteComd(0xAE);
SpiWriteComd(0xA2);
SpiWriteComd(0xA0);
SpiWriteComd(0xC8);
SpiWriteComd(0xF8);
SpiWriteComd(0x00);
SpiWriteComd(0x25);
SpiWriteComd(0x81);
SpiWriteComd(0x28);
SpiWriteComd(0x2C);
SpiWriteComd(0x2E);
SpiWriteComd(0x2F);
SpiWriteComd(0xAF); //Set Display ON
PutChinese(0,0,&CH_DOT[0][0]);
PutChinese(0,16,&CH_DOT[1][0]);
PutAscii(4,32,&ASCII_DOT['1' - 0x20][0]);
PutAscii(4,32+8,&ASCII_DOT['2' - 0x20][0]);
PutAscii(4,32+16,&ASCII_DOT['3' - 0x20][0]);
PutAscii(4,32+24,&ASCII_DOT['A' - 0x20][0]);
PutAscii(4,32+32,&ASCII_DOT['B' - 0x20][0]);
PutAscii(4,32+40,&ASCII_DOT['C' - 0x20][0]);
}
由于网上找的字模提取工具都不能满足自己的应用,所以就自己写了一个: