
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

