TA的每日心情 | 开心 2013-7-2 13:29 |
---|
签到天数: 1 天 连续签到: 1 天 [LV.1]初来乍到
|
上一章讲的是串口,由于时间的问题,没有讲到RX接收的中断处理。但是由于项目需要LCD的使用。所以这次讲STM32F103上使用的LCD一直到STM32F4上。
好的。首先可以看看一直好后的模块图。图在下面的附件中。
——————————————-分割线——————————————————
好了,这里使用的驱动是淘宝上买来学习的板子所给的资料。
在移植过程中很需要注意的是时钟配置的问题。
在我之前的AD模块移植时,提到了SYSCLK时钟。来做到具体的时间延时delay。
在徐州工程学院(开发手册)STM32之驱动移植杂记(2) 中可以看到。
好的首先我会传上STM32F1的LCD代码例程,然后新建一个STM32F4,进行移植。
文件见附件。
看LCD的初始化函数:
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6; //GPIO_Pin_10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure); //GPIOC
//GPIO_WriteBit(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6,Bit_SET);
GPIO_SetBits(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //
GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB
//GPIO_WriteBit(GPIOC,GPIO_Pin_All,Bit_SET);
GPIO_SetBits(GPIOB,GPIO_Pin_All);
delay_ms(50); // delay 50 ms
LCD_WriteReg(0x0000,0x0001);
delay_ms(50); // delay 50 ms
DeviceCode = LCD_ReadReg(0x0000);
下面的省略不需要了
。。。。
}
看上面的源代码,可以知道STMF1的配置,但是由于STM32F4的管脚配置有所变化,但是还是很好改的。
这里坐下分析,适合初学者。
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//GPIO结构体新建
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
//开GPIOC和GPIOB管脚时钟 RCC_APB2Periph_AFIO 和GPIO_Remap_SWJ_JTAGDisable在STM32F4中好像没了似的,这里先不考虑。
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6; //GPIO_Pin_10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure); //GPIOC
GPIO_SetBits(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6);
//置位管脚10,9,8,7,6,。
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //
GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB
GPIO_SetBits(GPIOB,GPIO_Pin_All);
//开所有GPIOB管脚并置位
delay_ms(50); // delay 50 ms
LCD_WriteReg(0x0000,0x0001);
delay_ms(50); // delay 50 ms
DeviceCode = LCD_ReadReg(0x0000);
//得到LCD的型号设备
下面的省略不需要了
。。。。
}
好了通过以前的GPIO讲解那么可以移植为:
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6; //GPIO_Pin_10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //推挽输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure); //GPIOC
GPIO_SetBits(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //
GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB
GPIO_SetBits(GPIOB,GPIO_Pin_All);
delay_ms(50); // delay 50 ms
LCD_WriteReg(0x0000,0x0001);
delay_ms(50); // delay 50 ms
DeviceCode = LCD_ReadReg(0x0000);
。。。
}
好了这样的话,这个初始化就行了。
由于LCD的函数实在太多,所以就不贴代码了看下面附件。
还有要改的是:宏定义:看代码:在lcd.h中
#define LCD_CS_SET GPIOC->BSRR=1<<9 //片选端口 PC9
#define LCD_RS_SET GPIOC->BSRR=1<<8 //数据/命令 PC8
#define LCD_WR_SET GPIOC->BSRR=1<<7 //写数据 PC7
#define LCD_RD_SET GPIOC->BSRR=1<<6 //读数据 PC6
#define LCD_CS_CLR GPIOC->BRR=1<<9 //片选端口 PC9
#define LCD_RS_CLR GPIOC->BRR=1<<8 //数据/命令 PC8
#define LCD_WR_CLR GPIOC->BRR=1<<7 //写数据 PC7
#define LCD_RD_CLR GPIOC->BRR=1<<6 //读数据 PC6
这里的GPIOC->BRR 和GPIOC->BSRR 是(STM32F10x)清零和置位寄存器的,在GPIO_SetBits(----); 函数中可以看到只用方法。
而在在STM32F4中相应的寄存器称呼变了,是BSRRLH和BSRRL .
所以改为:
#define LCD_CS_SET GPIOC->BSRRL=1<<9 //片选端口 PC9
#define LCD_RS_SET GPIOC->BSRRL=1<<8 //数据/命令 PC8
#define LCD_WR_SET GPIOC->BSRRL=1<<7 //写数据 PC7
#define LCD_RD_SET GPIOC->BSRRL=1<<6 //读数据 PC6
#define LCD_CS_CLR GPIOC->BSRRH=1<<9 //片选端口 PC9
#define LCD_RS_CLR GPIOC->BSRRH=1<<8 //数据/命令 PC8
#define LCD_WR_CLR GPIOC->BSRRH=1<<7 //写数据 PC7
#define LCD_RD_CLR GPIOC->BSRRH=1<<6 //读数据 PC6
这些从前几篇的移植可看出是一样的。但是今天关键讲的是时钟配置。
在STM32F4中的system_stm32f4xx.c文件下:
5. This file configures the system clock as follows:
*=============================================================================
*=============================================================================
* Supported STM32F4xx device revision | Rev A
*-----------------------------------------------------------------------------
* System Clock source | PLL (HSE)
*-----------------------------------------------------------------------------
* SYSCLK(Hz) | 168000000
*-----------------------------------------------------------------------------
* HCLK(Hz) | 168000000
*-----------------------------------------------------------------------------
* AHB Prescaler | 1
*-----------------------------------------------------------------------------
* APB1 Prescaler | 4
*-----------------------------------------------------------------------------
* APB2 Prescaler | 2
*-----------------------------------------------------------------------------
* HSE Frequency(Hz) | 8000000
*-----------------------------------------------------------------------------
* PLL_M | 8
*-----------------------------------------------------------------------------
* PLL_N | 336
*-----------------------------------------------------------------------------
* PLL_P | 2
*-----------------------------------------------------------------------------
* PLL_Q | 7
*-----------------------------------------------------------------------------
* PLLI2S_N | NA
*-----------------------------------------------------------------------------
* PLLI2S_R | NA
*-----------------------------------------------------------------------------
* I2S input clock | NA
*-----------------------------------------------------------------------------
* VDD(V) | 3.3
*-----------------------------------------------------------------------------
* High Performance mode | Enabled
*-----------------------------------------------------------------------------
* Flash Latency(WS) | 5
*-----------------------------------------------------------------------------
* Prefetch Buffer | OFF
*-----------------------------------------------------------------------------
* Instruction cache | ON
*-----------------------------------------------------------------------------
* Data cache | ON
*-----------------------------------------------------------------------------
* Require 48MHz for USB OTG FS, | Enabled
* SDIO and RNG clock |
*-----------------------------------------------------------------------------
*=============================================================================
这个是注解。从中可以看出所有的时钟。
SYSCLK(Hz) | 168000000是整个系统时钟。STM32F4最大支持168M的。
HSE Frequency(Hz) | 8000000外部晶振是8M
那对于我们这个LCD的移植就关注这个:
因为管脚的最大时钟是100M:
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
所以关注:
* PLL_M | 8 *-----------------------------------------------------------------------------
* PLL_N | 336
*-----------------------------------------------------------------------------
* PLL_P | 2
*-----------------------------------------------------------------------------
* PLL_Q | 7
*-----------------------------------------------------------------------------
才看这个不知道有什么用。继续看文件下面的宏定义:
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */这个是说PLL_VCO等于外部晶振8M除以PLL_M乘以PLL_N
#define PLL_M 8
#define PLL_N 336
那么从上面的值可以得到PLL_VCO =336M
/* SYSCLK = PLL_VCO / PLL_P */这个是说SYSCLK=PLL_VCO 除以PLL_P
#define PLL_P 2
那么从上面的值可以得到SYSCLK=168M
/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
#define PLL_Q 7
USB的时钟设置为336/7=48M
这样就大概知道系统时钟则呢么设置了吧。
好,还要看一个东西。在static void SetSysClock(void)中:红字部分
static void SetSysClock(void)
{
/******************************************************************************/
/* PLL (clocked by HSE) used as System clock source */
/******************************************************************************/
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable high performance mode, System frequency up to 168 MHz */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
PWR->CR |= PWR_CR_PMODE;
/* HCLK = SYSCLK / 1*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;//这个就是GPIO时钟分配的总线。一分频,也就是不分频。和系统时钟是一样的。
但是管脚最大只能是100M,所以我们需要把时钟设置为100M一下,或者将分频数改为2.
/* PCLK2 = HCLK / 2*/
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
/* PCLK1 = HCLK / 4*/
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
/* Configure the main PLL */
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
/* Enable the main PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till the main PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
/* Select the main PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_PLL;
/* Wait till the main PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
那么这里贴出改后的程序:
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M 8
#define PLL_N 192
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P 2
/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
#define PLL_Q 4
不改变分频。也就是系统时钟为96M
管脚是96M。随意更改。只要不超过100M
。
对于程序中的延时函数与上次说的是一样的。
其实还有一个关健的是硬件图的焊接。按照给的原理图焊接就行了。阻值一样就行。
|
|