day26:讀取LCD控制器ILI9341的ID


 

bsp_usart.h

#ifndef __BSP_USART_H__
#define __BSP_USART_H__

#include "stm32f10x.h"
#include "stdio.h"

// ----------------------- 串口1-USART1
// 使用哪個串口(串口1..5)
#define  DEBUG_USARTx                   USART1					
// APB2串口的同步時鍾
#define  DEBUG_USART_CLK                RCC_APB2Periph_USART1	
// APB2系統時鍾(因為串口USART1是掛載到APB2總線上的,所以要打開APB2總線的時鍾)
#define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd	
// 串口通信的波特率
#define  DEBUG_USART_BAUDRATE           19200


// ----------------------- USART GPIO 引腳宏定義
// GPIO引腳
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)	
// APB2系統時鍾(因為串口USART1是掛載到APB2總線上的,所以要打開APB2總線的時鍾)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd	

// GPIO引腳,發送接PA9,接收接PA10   
#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   		
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_9
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10

#define  DEBUG_USART_IRQ                USART1_IRQn
#define  DEBUG_USART_IRQHandler         USART1_IRQHandler

/* 串口調試配置函數:配置串口的相關參數,使能串口 */
void DEBUG_USART_Config(void);

/* 發送一個字節 */
void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t ch);

/* 發送字符串 */
void Usart_SendString(USART_TypeDef* pUSARTx, char* str);

#endif		/* __BSP_USART_H__ */

bsp_usart.c

 

#include "./usart/bsp_usart.h"

/* 串口中斷配置函數 */
static void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
  
	/* 嵌套向量中斷控制器組選擇 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
	/* 配置USART為中斷源 */
	NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
	/* 搶斷優先級*/
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	/* 子優先級 */
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	/* 使能中斷 */
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	
	/* 初始化配置NVIC */
	NVIC_Init(&NVIC_InitStructure);
}

/* 串口調試配置函數:配置串口的相關參數,使能串口 */
void DEBUG_USART_Config(void)
{
	/* 結構體變量聲明 */
	GPIO_InitTypeDef GPIO_InitStructure;		// GPIO
	USART_InitTypeDef USART_InitStructure;		// USART
	
	/* ------------ 第一步:初始化GPIO */
	// 打開串口GPIO的時鍾
	DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);	
	
	// 將USART Tx的GPIO配置為推挽復用模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;		// 引腳
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;				// 模式
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;			// 速率
	GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);	// 初始化結構體
	
	// 將USART Rx的GPIO配置為浮空輸入模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
	
	/* ------------ 第二步:配置串口的初始化結構體 */
	// 打開串口外設的時鍾
	DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
	/* 配置串口的工作參數 */
	// 波特率
	USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
	// 針數據字長
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	// 停止位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	// 校驗位
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	// 硬件流控制
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	// 工作模式,收發一起
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	// 完成串口的初始化配置
	USART_Init(DEBUG_USARTx, &USART_InitStructure);
	
	/* -------------------------------------------------------- */
	// 串口中斷優先級配置
	//NVIC_Configuration();	
	
	// 使能串口接收中斷
	//USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
	/* -------------------------------------------------------- */
	
	/* ------------ 第三步:使能串口 */
	USART_Cmd(DEBUG_USARTx, ENABLE);
}

/* 發送一個字節 */
void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t ch)
{
	/* 發送一個字節數據到USART */
	USART_SendData(pUSARTx, ch);
		
	/* 等待發送數據寄存器為空 */
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
}

/* 發送字符串 */
void Usart_SendString(USART_TypeDef* pUSARTx, char* str)
{
	unsigned int k=0;
	do 
	{
		Usart_SendByte(pUSARTx, *(str + k));
		k++;
	} while(*(str + k)!='\0');
  
	/* 等待發送完成 */
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC) == RESET);
}

/* 重定向c庫函數printf到串口,重定向后可使用printf函數 */
int fputc(int ch, FILE *f)
{
	/* 發送一個字節數據到串口 */
	USART_SendData(DEBUG_USARTx, (uint8_t) ch);
		
	/* 等待發送完畢 */
	while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);		
	
	return (ch);
}

/* 重定向c庫函數scanf到串口,重寫向后可使用scanf、getchar等函數 */
int fgetc(FILE *f)
{
	/* 等待串口輸入數據 */
	while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);

	return (int)USART_ReceiveData(DEBUG_USARTx);
}

bsp_ili9341_lcd.h

 

#ifndef __BSP_ILI9341_LCD_H__
#define __BSP_ILI9341_LCD_H__

#include "stm32f10x.h"

/* ------------------------------- 變量宏定義 ------------------------------ */
// CS(NSS)引腳 片選選普通GPIO即可
#define			ILI9341_CS_CLK			RCC_APB2Periph_GPIOC   
#define			ILI9341_CS_PORT			GPIOC
#define			ILI9341_CS_PIN			GPIO_Pin_4

// RD引腳 片選選普通GPIO即可
#define			ILI9341_RD_CLK			RCC_APB2Periph_GPIOC   
#define			ILI9341_RD_PORT			GPIOC
#define			ILI9341_RD_PIN			GPIO_Pin_5

// WE引腳 片選選普通GPIO即可
#define			ILI9341_WE_CLK			RCC_APB2Periph_GPIOC   
#define			ILI9341_WE_PORT			GPIOC
#define			ILI9341_WE_PIN			GPIO_Pin_6

// DC引腳 片選選普通GPIO即可
#define			ILI9341_DC_CLK			RCC_APB2Periph_GPIOC   
#define			ILI9341_DC_PORT			GPIOC
#define			ILI9341_DC_PIN			GPIO_Pin_7

// BK引腳 片選選普通GPIO即可
#define			ILI9341_BK_CLK			RCC_APB2Periph_GPIOD  
#define			ILI9341_BK_PORT			GPIOD
#define			ILI9341_BK_PIN			GPIO_Pin_2

// D0-D15引腳 片選選普通GPIO即可(數據引腳)
#define			ILI9341_DATA_CLK		RCC_APB2Periph_GPIOB   
#define			ILI9341_DATA_PORT       GPIOB
#define			ILI9341_DATA_PIN        GPIO_Pin_All


/* ------------------------------- 函數宏定義 ------------------------------ */
// BK:背光引腳的GPIO打開或關閉
#define			LCD_BK_ON()     		GPIO_ResetBits(ILI9341_BK_PORT, ILI9341_BK_PIN)
#define			LCD_BK_OFF()     		GPIO_SetBits(ILI9341_BK_PORT, ILI9341_BK_PIN)

// CS
#define			LCD_CS_HIGH()     		GPIO_SetBits(ILI9341_CS_PORT, ILI9341_CS_PIN)
#define			LCD_CS_LOW()     		GPIO_ResetBits(ILI9341_CS_PORT, ILI9341_CS_PIN)

// RD
#define			LCD_RD_HIGH()     		GPIO_SetBits(ILI9341_RD_PORT, ILI9341_RD_PIN)
#define			LCD_RD_LOW()     		GPIO_ResetBits(ILI9341_RD_PORT, ILI9341_RD_PIN)

// WE
#define			LCD_WE_HIGH()     		GPIO_SetBits(ILI9341_WE_PORT, ILI9341_WE_PIN)
#define			LCD_WE_LOW()     		GPIO_ResetBits(ILI9341_WE_PORT, ILI9341_WE_PIN)

// DC
#define			LCD_DC_HIGH()     		GPIO_SetBits(ILI9341_DC_PORT, ILI9341_DC_PIN)
#define			LCD_DC_LOW()     		GPIO_ResetBits(ILI9341_DC_PORT, ILI9341_DC_PIN)

// D0-D15
#define			LCD_DATA_OUT(data)		GPIO_Write(ILI9341_DATA_PORT, data)		// ILI9341_DATA_PORT->ODR = data	
#define			LCD_DATA_IN()			GPIO_ReadInputData(ILI9341_DATA_PORT)	

/* ------------------------------- 函數 ------------------------------ */
/* ILI9341初始化 */
void ILI9341_GPIO_Init(void);

/* 寫命令 */
void ILI9341_Write_Cmd(uint16_t cmd);

/* 寫數據 */
void ILI9341_Write_Data(uint16_t data);

/* 讀數據 */
uint16_t ILI9341_Read_Data(void);

/* 讀取ID */
uint16_t ILI9341_Read_ID(void);


#endif		/* __BSP_ILI9341_LCD_H__ */

bsp_ili9341_lcd.c

/*
1.初始化跟液晶控制相關的引腳
  初始化時要確認配置GPIOB使用的PB3/PB4引腳,
	需要重定義才能用作普通GPIO
	
2.模擬8080時序
  寫命令
	寫數據
	讀數據
	
3.通過讀取ILI9341的ID測試函數
4.初始化液晶屏及配置掃描方向
5.往LCD坐標x,y寫一個特定顏色像素點
*/

#include "./lcd/bsp_ili9341_lcd.h"

// 這里定義一個宏,目的是不用大幅度修改代碼,方便程序維護
#define ILI9341_DELAY()		ILI9341_Delay(10)

static void ILI9341_Delay(__IO uint32_t nCount)
{
	for(; nCount!=0; nCount--);
}

/* ILI9341初始化 */
void ILI9341_GPIO_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	/*
	把PB3,PB4引腳用作普通GPIO
	因為PB3和PB4引腳和JTAG功能引腳共用,所以要把JTAG功能禁用,讓PB3和PB4引腳可以使用
	*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);		// 使能復用時鍾AFIO
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	
	/* 使能引腳相關的時鍾 */
 	RCC_APB2PeriphClockCmd(ILI9341_CS_CLK|
							ILI9341_RD_CLK|
							ILI9341_WE_CLK|
							ILI9341_DC_CLK|
							ILI9341_BK_CLK|
							ILI9341_DATA_CLK, ENABLE);
	
	/* 默認全配置成輸出模式 */
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	
	// CS
	GPIO_InitStructure.GPIO_Pin = ILI9341_CS_PIN;
	GPIO_Init(ILI9341_CS_PORT, &GPIO_InitStructure);	
	
	// RD
	GPIO_InitStructure.GPIO_Pin = ILI9341_RD_PIN;
	GPIO_Init(ILI9341_RD_PORT, &GPIO_InitStructure);
	
	// WE
	GPIO_InitStructure.GPIO_Pin = ILI9341_WE_PIN;
	GPIO_Init(ILI9341_DC_PORT, &GPIO_InitStructure);
	
	// DC
	GPIO_InitStructure.GPIO_Pin = ILI9341_DC_PIN;
	GPIO_Init(ILI9341_WE_PORT, &GPIO_InitStructure);
	
	// BK
	GPIO_InitStructure.GPIO_Pin = ILI9341_BK_PIN;
	GPIO_Init(ILI9341_BK_PORT, &GPIO_InitStructure);
	
	// D0-D15
	GPIO_InitStructure.GPIO_Pin = ILI9341_DATA_PIN;
	GPIO_Init(ILI9341_DATA_PORT, &GPIO_InitStructure);
	
	// 默認點亮背光
	LCD_BK_ON();
}

/* 寫命令:根據時序寫 */
void ILI9341_Write_Cmd(uint16_t cmd)
{
	LCD_CS_LOW();
	ILI9341_DELAY();
	
	LCD_DC_LOW();
	ILI9341_DELAY();
	
	LCD_RD_HIGH();
	ILI9341_DELAY();
	
	LCD_DATA_OUT(cmd);
	ILI9341_DELAY();
	
	LCD_WE_LOW();
	ILI9341_DELAY();
	
	LCD_WE_HIGH();
	ILI9341_DELAY();
	
	LCD_CS_HIGH();
}

/* 寫數據:根據時序寫 */
void ILI9341_Write_Data(uint16_t data)
{
	LCD_CS_LOW();
	ILI9341_DELAY();
	
	LCD_DC_HIGH();	 		/* 和寫命令的區別,這里DC為高電平 */
	ILI9341_DELAY(); 
	
	LCD_RD_HIGH();
	ILI9341_DELAY();
	
	LCD_DATA_OUT(data);	
	ILI9341_DELAY();
	
	LCD_WE_LOW();	
	ILI9341_DELAY();
	
	LCD_WE_HIGH();	
	ILI9341_DELAY();
	
	LCD_CS_HIGH();	
}

/* 讀數據:根據時序寫 */
uint16_t ILI9341_Read_Data()
{
	uint16_t data = 0;
	
	// 切換data端口為輸入模式【因為輸出模式常用,輸入不常用,所以默認定義成輸出模式】
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = ILI9341_DATA_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_Init(ILI9341_DATA_PORT, &GPIO_InitStructure);
	
	/* 根據時序寫 */
	LCD_CS_LOW();
	ILI9341_DELAY();
	
	LCD_DC_HIGH();
	ILI9341_DELAY();
	
	LCD_WE_HIGH();	
	ILI9341_DELAY();	
	
	LCD_RD_LOW();
	ILI9341_DELAY();	
	
	data = LCD_DATA_IN();		/* 讀取到的數據 */
	ILI9341_DELAY();
		
	LCD_RD_HIGH();
	ILI9341_DELAY();	

	LCD_CS_HIGH();
	
	/* 切換data端口為輸出模式,方便其他方法使用 */
	GPIO_InitStructure.GPIO_Pin = ILI9341_DATA_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(ILI9341_DATA_PORT, &GPIO_InitStructure);
	
	// 返回數據
	return data;
}

/* 讀取ID */
uint16_t ILI9341_Read_ID()
{
	uint16_t temp = 0 ;
	
	// 發送讀取ID的命令:0XD3
	ILI9341_Write_Cmd(0xD3);
	
	// 讀取前面兩個用不到的字節
	ILI9341_Read_Data();
	ILI9341_Read_Data();
	
	// 開始正式的讀取數據
	temp = ILI9341_Read_Data();
	// 將讀取到的數據向左移動8位,騰出位置
	temp <<= 8;
	// 繼續讀取數據放到temp變量中
	temp |= ILI9341_Read_Data();
	
	// 返回讀取到的ID數據
	return temp;
}

main.c

#include "stm32f10x.h"
#include "./usart/bsp_usart.h"
#include "./led/bsp_led.h" 
#include "./lcd/bsp_ili9341_lcd.h"

int main(void)
{	
	/* LED引腳初始化 */	
	//LED_GPIO_Config();
	
	/* USART串口初始化 */
	DEBUG_USART_Config();
	
	printf("這是一個LCD實驗\r\n");
	
	/* ILI9341初始化 */
	ILI9341_GPIO_Init();
	
	// 讀取ID
	printf("讀取到的ID = %x\r\n\r\n", ILI9341_Read_ID());
	
	while(1);	
}

 實驗結果:返回9341,是ILI9341的ID

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM