LCD1602
每行显示16个字符 一共2行
DB0--PB5
DB1--PB6
DB2--PB7
DB3--PB8
DB4--PB9
DB5--PC0
DB6--PC1
DB7--PC2
控制
使能PB4---------------- --[1--延时--0完成使能]
数据/命令选择 PC6 --- [1-数据 0-命令]
读/写选择 PA11------ [1-读 0-写]
分析一个数据过来比如11001010
那么分配一下
DB0--PB5--0
DB1--PB6--1
DB2--PB7--0
DB3--PB8--1
DB4--PB9--0
DB5--PC0--0
DB6--PC1--1
DB7--PC2--1
代码如何写呢?一个数据过来 需要分割2部分5BIT去PB 3BIT去PC
void Lcd1602_SendByte(unsigned char byte)
{
unsigned short value = 0;
value = GPIO_ReadOutputData(GPIOB); //读取GPIOB的数据
value &= ~(0x001F << 5); //清除bit5~8
value |= ((unsigned short)byte & 0x001F) << 5; //将要写入的数据取低5位并左移5位
GPIO_Write(GPIOB, value); //写入GPIOB
value = GPIO_ReadOutputData(GPIOC); //读取GPIOC的数据
value &= ~(0x0007 << 0); //清除bit0~2
value |= ((unsigned short)byte & 0x00E0) >> 5; //将要写入的数据取高3位并右移5位
GPIO_Write(GPIOC, value); //写入GPIOC
DelayUs(10);
}
可以看到用了value整体处理 而不是一个一个去控制,因为设计好了,你看
先 value = GPIO_ReadOutputData(GPIOB); //读取GPIOB的数据它包含了PB的全部引脚比如PB3它现在是高电平在亮灯的话那么PB3就是1 一起读出来是unsigned short
在 value &= ~(0x001F << 5); //清除bit5~8 因为我们用的是PB56789 把我们控制的操作 不会干扰PB3的LED
在 value |= ((unsigned short)byte & 0x001F) << 5; //其实这句话才体现了不会干扰PB3的LED 其他位置不变 在约定的地方|进去了byte参数的部分
在 GPIO_Write(GPIOB, value); //完成目标控制 并且不干扰别的管脚
可以看到这个依赖硬件的设计 管脚尽量靠在一起 操作方便
开始流程:
初始化--全部设置为output--开始初始化程序--
Lcd1602_WriteCom(0x38);
DelayXms(5);
Lcd1602_WriteCom(0x38);
DelayXms(5);
Lcd1602_WriteCom(0x38);
Lcd1602_WriteCom_Busy(0x38);
Lcd1602_WriteCom_Busy(0x08);
Lcd1602_WriteCom_Busy(0x01);
Lcd1602_WriteCom_Busy(0x06);
Lcd1602_WriteCom_Busy(0x0c);
--开始显示
关键函数Lcd1602_SendByte开始分析
GPIO的库函数控制 做个小测试吧
+++++++++++++++++++mcube+++在开始+++
https://www.cnblogs.com/will-king0308/p/8656077.html
8个数据
pa0 1 2 3 4 5 6 7-----D0 1 2 3 4 5 6 7
这样直接连接
另外3个需要编程的
pB7---rs
pb6--rw
pb5-e
供电
1---背光走3.3VSTM32板子
2---LCD上电用USB GNB+5V 3.3V 因为5V是开机的 3.3v是三号脚对比的
最后上图 是比较好看的
开始逻辑 8+3 全部的编程IO都是基础的GPIO_Mode_Out_PP
+++++++++++++++++麒麟座OK+++++++++
可以直接运行
如果麒麟座第一次烧录以后 此后STLINK无法连接 无法KEIL烧录 用3。3V拉一下R7也就是BOOT0
目前BOOT 0 1 都是GND的 你板子下电 usbhub一起供电关闭
短接R7和3.3V 上电 就可以烧录了
第一步 提供US延时 利用tim
void MX_TIM2_Init(void)
{
htim2.Instance = TIM2;
htim2.Init.Prescaler = 72-1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 1000-1;
void TIM2_Delay(int us)
{
uint16_t differ=us;
if(differ>999)return;
HAL_TIM_Base_Start(&htim2);
__HAL_TIM_SET_COUNTER(&htim2,0);
while(__HAL_TIM_GET_COUNTER(&htim2) < differ);
HAL_TIM_Base_Stop(&htim2);
}
第二部IO对应有问题 下面是OK的
#define RS_H HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);
#define RS_L HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
#define RW_H HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_SET);
#define RW_L HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_RESET);
#define EN_H HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);
#define EN_L HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
全部代码
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void TIM2_Delay(int us)
{
uint16_t differ=us;
if(differ>999)return;
HAL_TIM_Base_Start(&htim2);
__HAL_TIM_SET_COUNTER(&htim2,0);
while(__HAL_TIM_GET_COUNTER(&htim2) < differ);
HAL_TIM_Base_Stop(&htim2);
}
/* USER CODE END 0 */
#define RS_H HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);
#define RS_L HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
#define RW_H HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_SET);
#define RW_L HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_RESET);
#define EN_H HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);
#define EN_L HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
uint32_t GReadGPIOOutput(GPIO_TypeDef* GPIOx)
{return GPIOx->ODR;}
void GWriteGPIOOutput(GPIO_TypeDef* GPIOx,uint32_t value)
{GPIOx->ODR = value;}
void Lcd1602_SendByte(unsigned char byte)
{
unsigned short value = 0;
value = GReadGPIOOutput(GPIOB); //读取GPIOB的数据
value &= ~(0x001F << 5); //清除bit5~8
value |= ((unsigned short)byte & 0x001F) << 5; //将要写入的数据取低5位并左移5位
GWriteGPIOOutput(GPIOB, value); //写入GPIOB
value = GReadGPIOOutput(GPIOC); //读取GPIOC的数据
value &= ~(0x0007 << 0); //清除bit0~2
value |= ((unsigned short)byte & 0x00E0) >> 5; //将要写入的数据取高3位并右移5位
GWriteGPIOOutput(GPIOC, value); //写入GPIOC
TIM2_Delay(10);
}
void Lcd1602_WriteCom(unsigned char byte)
{
RS_L;
RW_L;
Lcd1602_SendByte(byte);
EN_H;
TIM2_Delay(20);
EN_L;
TIM2_Delay(5);
}
void Lcd1602_WriteCom_Busy(unsigned char byte)
{HAL_Delay(2);
RS_L;
RW_L;
Lcd1602_SendByte(byte);
EN_H;
TIM2_Delay(20);
EN_L;
TIM2_Delay(5);
}
void Lcd1602_WriteData(unsigned char byte)
{
RS_H;
RW_L;
Lcd1602_SendByte(byte);
EN_H;
TIM2_Delay(20);
EN_L;
TIM2_Delay(5);
}
void Lcd1602_Init(void)
{
HAL_Delay(15);
Lcd1602_WriteCom(0x38);
HAL_Delay(5);
Lcd1602_WriteCom(0x38);
HAL_Delay(5);
Lcd1602_WriteCom(0x38);
Lcd1602_WriteCom_Busy(0x38);
Lcd1602_WriteCom_Busy(0x08);
Lcd1602_WriteCom_Busy(0x01);
Lcd1602_WriteCom_Busy(0x06);
Lcd1602_WriteCom_Busy(0x0c);
EN_L;
}
void lcd_char_write(unsigned int x_pos,unsigned int y_pos,unsigned char lcd_dat) /*LCD1602 字符写入*/
{
x_pos &= 0x0f;
y_pos &= 0x01;
if(y_pos==1) x_pos += 0x40;
x_pos += 0x80;
Lcd1602_WriteCom_Busy(x_pos);
Lcd1602_WriteData(lcd_dat);
}
#include <stdarg.h>
void Lcd1602_DisString(unsigned char pos, char *fmt,...)
{
unsigned char LcdPrintfBuf[33];
unsigned char count = 0;
unsigned char remain = 0; //一行剩余空间
va_list ap;
unsigned char *pStr = LcdPrintfBuf;
va_start(ap,fmt);
vsprintf((char *)LcdPrintfBuf, fmt, ap);
va_end(ap);
remain = 0x8f - pos; //这里解决bug,以前只管写16次,这次要根据开始的位置来计算
Lcd1602_WriteCom_Busy(pos);
while(*pStr != 0)
{
Lcd1602_WriteData(*pStr++);
if(++count > remain && pos <= 0x8f)
{
count = 0;
Lcd1602_WriteCom_Busy(0xC0);
HAL_Delay(1);
}
}
}
/**
* @brief The application entry point.
* @retval int
*/
unsigned char temp_table[] ={"TempNow: . C"};
unsigned char temp_set_table[]={"MMX:70C IN: "};
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
Lcd1602_Init();
// Lcd1602_DisString(0x80, "OneNET-IOT");
// Lcd1602_DisString(0xC0, "China Mobile");
for(int i=0;i<16;i++)
lcd_char_write(i,0,temp_table[i]);
for(int j=0;j<16;j++)
lcd_char_write(j,1,temp_set_table[j]);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
//HAL_Delay(200);
for(int i=0;i<1000;i++) TIM2_Delay(200);
HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
麒麟座的使用
1---STLINK直接 连接103的 这个要转接一下
也就是用麒麟座需要自己多一个线
2--每次KEIL烧录失败 你需要板子下电 短句R7-3.3V然后上电 烧录 完毕以后 在下电上电run