实验指导书1-5 - 图文

更新时间:2024-06-03 12:33:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

《嵌入式系统开发》0806504130

实验指导书

实验一、按键输入及LED实验 2课时 实验二、STM32串口实验 2课时 实验三、定时器中断实验 2课时 实验四 PWM输出实验 2课时 实验五 TFTLCD显示实验 2课时 实验六 AD转换实验 2课时 实验七 UCOSII任务调度实验 4课时

金陵科技学院智控学院 自动化

《嵌入式系统开发》0806504130 实验指导书

实验一 按键输入及LED实验

实验时间:2016-03-29(周二3,4节),实验学时:2,实验地点:C105

一、实验目的与要求:

(1)熟悉MDK的编程环境;

(2)掌握基于固件库MDK5工程模板的方法;

(2)掌握STM32的IO口作为输入、输出使用的方法;

二、实验器材:

计算机,STM32F103RCT6实验平台。

三、实验过程

1.熟悉led和按键硬件电路; 2.建立工程模版;

3.根据实验内容编写主程序及应用程序 4.下载调试及仿真。

3.1实验内容:通过MiniSTM32开发板上载有的3个按钮(KEY0/KEY1/WK_UP),来控制板上的2个LED,其中KEY0控制DS0,按一次亮,再按一次,就灭。KEY1控制DS1,效果同KEY0。WK_UP按键则同时控制DS0和DS1,按一次,他们的状态就翻转一次。 3.2本实验用到的硬件资源有: 1) 指示灯DS0、DS1

2) 3个按键:KEY0、KEY1和KEY_UP。 3.3、硬件设计

(1)输出引脚LED(DS0和DS1)。其电路在ALIENTEK MiniSTM32开发板上默认是已经连接好了的。DS0接PA8,DS1接PD2。所以在硬件上不需要动任何东西。其连接原理如图1.1所示。

图1.1 LED与STM32连接原理图

(2)输入引脚,在MiniSTM32开发板上的按键KEY0连接在PC5上、KEY1连接在PA15上、WK_UP连接在PA0上。如图1.2所示:

图1.2 按键与STM32连接原理图

1

《嵌入式系统开发》0806504130 实验指导书

这里需要注意的是:KEY0和KEY1是低电平有效的,而WK_UP是高电平有效的,除了KEY1有上拉电阻(与JTDI共用),其他两个都没有上下拉电阻,所以,需要在STM32内部设置上下拉。

3.4、软件设计

首先建立工程目录,如下图1.3所示。

① 组USER下面存放的主要是用户代码。system_stm32f10x.c里面主要是系统时钟初始化函数SystemInit相关的定义,一般情况下文件用户不需要修改。stm32f10x_it.c里面存放的是部分中断服务函数。main.c函数主要存放的是主函数。

② 组HARDWARE下面存放的是每个实验的外设驱动代码,他的实现是通过调用FWLib下面的固件库文件实现的,比如led.c 里面调用stm32f10x_gpio.c里面的函数对led 进行初始化,这里面的函数是讲解的重点。后面的实验中可以看到会引入多个源文件。

③ 组SYSTEM是ALIENTEK提供的共用代码,包含Systick延时函数,IO口位带操作以及串口相关函数。

④ 组CORE下面存放的是固件库必须的核心文件和启动文件。这里面的文件用户不需要修改。

⑤ 组FWLib下面存放的是ST官方提供的外设驱动固件库文件,这些文件大家可以根据工程需要来添加和删除。每个stm32f10x_ppp.c源文件对应一个stm32f10x_ppp.h头文件。 ⑥ HARDWARE主要添加本项目中用到的.c文件。

图1.3 工程目录

在HARDWARE文件夹目录下,建立key文件夹,放key.c、key.h文件,建立led文件夹,放led.c、led.h文件。

在Manage Project Items管理里面新建一个HARDWARE的组,并把led.c、key.c加入到这个组里面;点击魔术棒,添加led.h和key.h所在的目录,然后就可以在HARDWARE下完成key.c、key.h、led.c、led.h文件的编写。 3.4.1输出引脚配置

STM32的IO口相比51而言要复杂得多,所以使用起来也困难很多。首先STM32的IO口可以由软件配置成如下8种模式:

1、输入浮空 2、输入上拉 3、输入下拉 4、模拟输入 5、开漏输出

2

《嵌入式系统开发》0806504130 实验指导书

6、推挽输出

7、推挽式复用功能 8、开漏复用功能

在HARDWARE->LED文件夹下面,保存为led.c,内容为: #include \void LED_Init(void) {

GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|

RCC_APB2Periph_GPIOD, ENABLE); //使能PA,PD端口时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //LED0-->PA.8 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//IO口速度为50MHz GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.8 GPIO_SetBits(GPIOA,GPIO_Pin_8); //PA.8 输出高 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//LED1-->PD.2 端口配置,推挽输出 GPIO_Init(GPIOD, &GPIO_InitStructure);//推挽输出,IO口速度为50MHz GPIO_SetBits(GPIOD,GPIO_Pin_2); //PD.2输出高 }

头文件led.h如下: #ifndef __LED_H #define __LED_H #include \//LED端口定义

#define LED0 PAout(8) // PA8 #define LED1 PDout(2) // PD2

void LED_Init(void);//初始化 #endif

这里使用的是位带操作来实现操作某个IO口的1个位的,通过位带操作PA8输出高低电平从而控制LED0的方法如下:

LED0=1; //通过位带操作控制LED0的引脚PA8输出高电平 LED0=0; //通过位带操作控制LED0的引脚PA8输出低电平 同样我们也可以使用固件库操作和寄存器操作 来实现IO口操作。库函数操作方法如下:

GPIO_SetBits(GPIOA, GPIO_Pin_8); //设置GPIOA8输出1,等同LED0=1; GPIO_ResetBits (GPIOA, GPIO_Pin_8); //设置GPIOA8输出0,等同LED0=0;

库函数操作就直接调用两个函数即可控制IO 输出高低电平。我们也通过直接操作寄存器

BRR和BSRR的方式来操作IO口输出高低电平,方法如下: GPIOA->BRR=GPIO_Pin_8; //设置GPIOA.8输出1,等同LED0=1; GPIOA->BSRR=GPIO_Pin_8; //设置GPIOA.8输出0,等同LED0=0;

对于上面三种方法,大家根据自己喜好来选择一种即可。在IO 口速度没有太大要求的情况下效果都是一样的。 3.4.2输入引脚配置

3

《嵌入式系统开发》0806504130 实验指导书

在HARDWARE文件夹下建立key.c文件以及头文件key.h。下面我们首先打开key.c文件,key.c代码如下:

#include \#include \//按键初始化函数

//PA15 和PC5 设置成输入 void KEY_Init(void) {

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);//使能PORTA,PORTC时钟

GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //关闭jtag,使能SWD,可以用SWD模式调试

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PA15

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA15

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//PC5

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入 GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC5

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//PA0

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0 }

//按键处理函数 //返回按键值

//mode:0,不支持连续按;1,支持连续按; //返回值:

//0,没有任何按键按下 //KEY0_PRES,KEY0按下 //KEY1_PRES,KEY1按下 //WKUP_PRES,WK_UP按下

//注意此函数有响应优先级,KEY0>KEY1>WK_UP!! u8 KEY_Scan(u8 mode) {

static u8 key_up=1;//按键按松开标志 if(mode)key_up=1; //支持连按 if(key_up&&(KEY0==0||KEY1==0||WK_UP==1)) {

delay_ms(10);//去抖动 key_up=0;

if(KEY0==0)return KEY0_PRES;

4

《嵌入式系统开发》0806504130 实验指导书

else if(KEY1==0)return KEY1_PRES; else if(WK_UP==1)return WKUP_PRES;

}else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1; return 0;// 无按键按下 }

Key.h代码如下: #ifndef __KEY_H #define __KEY_H #include \

#define KEY0 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)//读取按键0 #define KEY1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)//读取按键1 #define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键2 #define KEY0_PRES 1 //KEY0 #define KEY1_PRES 2 //KEY1 #define WKUP_PRES 3 //WK_UP void KEY_Init(void);//IO初始化

u8 KEY_Scan(u8 mode); //按键扫描函数 #endif

3.4.3主程序的编写:

#include \#include \#include \#include \

//跑马灯实验 int main(void) {

…… }

四、实验结果与分析

给出程序编译过程中曾经出现的错误,及相应解决方法; 给出实物运行照片。

5

《嵌入式系统开发》0806504130 实验指导书

实验二 STM32串口实验

实验时间:2016-04-05(周二3,4节),实验学时:2,实验地点:C105

一、实验目的与要求:

(1)熟悉MDK的编程环境;

(2)掌握基于固件库MDK5工程模板的方法;

(2)掌握STM32串口的原理,理解其作为软件开发的重要调试手段;

二、实验器材:

计算机,STM32F103RCT6实验平台。

三、实验过程

3.1实验内容:实现利用串口1,每隔0.5s发送

13自动化 学号:123456678 姓名: XXX

到电脑上,同时STM32接收从电脑串口调试软件发过来的数据,把发送过来的数据直接送回给电脑串口调试软件。并闪烁LED0,提示系统正在运行。 3.2实验过程:

1、对于复用功能的IO,我们首先要使能GPIO时钟,然后使能串口时钟; 2、把GPIO模式设置为复用功能对应的模式;

3、串口参数的初始化设置,包括波特率,停止位等等参数; 4、开启串口中断,初始化NVIC设置中断优先级别; 5、使能串口;

6、编写中断服务函数。 3.3本实验用到的硬件资源有: 本实验需要用到的硬件资源有: 1) 指示灯DS0

2) 串口1 图2.1 硬件连接图示意图

本实验用到的串口1与USB串口并没有在PCB上连接在一起,需要通过跳线帽来连接一下。这里我们把P4的RXD和TXD用跳线帽与PA9和PA10连接起来。如图2.1所示。

连接上这里之后,我们在硬件上就设置完成了,可以开始软件设计了。 3.4本实验涉及的库函数:

下面简单介绍这几个与串口基本配置直接相关的几个固件库函数。这些函数和定义主要分布在stm32f10x_usart.h和stm32f10x_usart.c文件中。

1.串口时钟使能。串口是挂载在APB2下面的外设,所以使能函数为: RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1);

2.串口复位。当外设出现异常的时候可以通过复位设置,实现该外设的复位,然后重新配置这个外设达到让其重新工作的目的。一般在系统刚开始配置外设的时候,都会先执行复位该外设的操作。复位的是在函数USART_DeInit()中完成:

void USART_DeInit(USART_TypeDef* USARTx);//串口复位 比如我们要复位串口1,方法为:

USART_DeInit(USART1); //复位串口1

3.串口参数初始化。串口初始化是通过USART_Init()函数实现的,

void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct); 这个函数的的第一个入口参数是指定初始化的串口标号,这里选择USART1。

第二个入口参数是一个USART_InitTypeDef类型的结构体指针,这个结构体指针的成员变量用来设置串口的一些参数。一般的实现格式为:

USART_InitStructure.USART_BaudRate = bound; //波特率;

6

《嵌入式系统开发》0806504130 实验指导书

USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式

4.数据发送与接收。STM32的发送与接收是通过数据寄存器USART_DR来实现的,这是一个双寄存器,包含了TDR和RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到收据的时候,也是存在该寄存器内。

STM32库函数操作USART_DR寄存器发送数据的函数是:

void USART_SendData(USART_TypeDef* USARTx, uint16_t Data); 通过该函数向串口寄存器USART_DR写入一个数据。

STM32库函数操作USART_DR寄存器读取串口接收到的数据的函数是: uint16_t USART_ReceiveData(USART_TypeDef* USARTx);

5.串口状态。串口的状态可以通过状态寄存器USART_SR读取。

6.串口使能。串口使能是通过函数USART_Cmd()来实现的,这个很容易理解,使用方

法是: USART_Cmd(USART1, ENABLE); //使能串口

7.开启串口响应中断。有些时候当我们还需要开启串口中断,那么我们还需要使能串口中断,使能串口中断的函数是:

void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState)

这个函数的第二个入口参数是标示使能串口的类型,也就是使能哪种中断,因为串口的中断类型有很多种。比如在接收到数据的时候(RXNE读数据寄存器非空),我们要产生中断,那么我们开启中断的方法是:

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断,接收到数据中断 我们在发送数据结束的时候(TC,发送完成)要产生中断,那么方法是: USART_ITConfig(USART1,USART_IT_TC,ENABLE);

8.获取相应中断状态。当我们使能了某个中断的时候,当该中断发生了,就会设置状态寄存器中的某个标志位。经常我们在中断处理函数中,要判断该中断是哪种中断,使用的函数是: ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)

比如我们使能了串口发送完成中断,那么当中断发生了, 我们便可以在中断处理函数中调用这个函数来判断到底是否是串口发送完成中断,方法是:

USART_GetITStatus(USART1, USART_IT_TC) 返回值是SET,说明是串口发送完成中断发生。 9.软件设计(学生完成)

请自行编写软件。void uart_init(u32 bound)函数main函数。 四、实验结果与分析

1.给出程序编译过程中曾经出现的错误,及相应解决方法;

2. 打开XCOM V1.4,设置串口为开发板的USB转串口(CH340虚拟串口),调试结果截图到这里。

7

《嵌入式系统开发》0806504130 实验指导书

实验三 STM32外部中断实验

实验时间:2016-04-19(周二3,4节),实验学时:2,实验地点:C105

一、实验目的与要求:

(1)熟悉MDK的编程环境;

(2)掌握STM32外部中断配置的基本方法; (2)掌握使用IO口作为外部中断的一般步骤;

二、实验器材:

计算机,STM32F103RCT6实验平台。

三、实验过程

1.熟悉led和按键硬件电路; 2.建立工程模版;

3.根据实验内容编写主程序及应用程序 4.下载调试及仿真。 3.1实验内容:

STM32的每个IO都可以作为外部中断的中断输入口。通过MiniSTM32开发板上载有的3个按钮(KEY0/KEY1/WK_UP),来控制板上的2个LED,其中KEY0控制DS0,按一次亮,再按一次,就灭。KEY1控制DS1,效果同KEY0。WK_UP按键则同时控制DS0和DS1,按一次,他们的状态就翻转一次。

3.2本实验用到的硬件资源有: 1) 指示灯DS0、DS1

2) 3个按键:KEY0、KEY1和KEY_UP。 3.3、硬件设计

(1)输出引脚LED(DS0和DS1)。其电路在ALIENTEK MiniSTM32开发板上默认是已经连接好了的。DS0接PA8,DS1接PD2。所以在硬件上不需要动任何东西。其连接原理如图3.1所示。

图3.1 LED与STM32连接原理图

(2)输入引脚,在MiniSTM32开发板上的按键KEY0连接在PC5上、KEY1连接在PA15上、WK_UP连接在PA0上。如图3.2所示:

图3.2 按键与STM32连接原理图

8

《嵌入式系统开发》0806504130 实验指导书

3.4 STM32 外部中断原理 (0)简介

STM32的每个IO都可以作为外部中断的中断输入口,这点也是STM32的强大之处。STM32F103的中断控制器支持19个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。STM32F103的19个外部中断为:

线0~15:对应外部IO口的输入中断。 线16:连接到PVD输出。 线17:连接到RTC闹钟事件。 线18:连接到USB唤醒事件。

GPIO的管脚GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线15~0。这样每个中断线对应了最多7个IO口,以线0为例:它对应了GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、GPIOE.0、GPIOF.0、GPIOG.0。而中断线每次只能连接到1个IO 口上,这样就需要通过配置来决定对应的中断线配置到哪个GPIO上。 (1)配置GPIO与中断线的映射关系

在库函数中,配置GPIO与中断线的映射关系的函数GPIO_EXTILineConfig()来实现的: void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) 该函数将GPIO端口与中断线映射起来,使用范例是:

GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);

将中断线2与GPIOE映射起来,那么很显然是GPIOE.2与EXTI2中断线连接了。设置好中断线映射之后,那么到底来自这个IO 口的中断是通过什么方式触发的呢?接下来我们就要设置该中断线上中断的初始化参数了。 (2)中断的初始化

中断线上中断的初始化是通过函数EXTI_Init()实现的。EXTI_Init()函数的定义是: void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct); 使用方法如下:

EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line=EXTI_Line4;

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE;

EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器

上面的例子第一个参数是中断线的标号,取值范围为EXTI_Line0~EXTI_Line15。第二个参数是中断模式,可选值为中断EXTI_Mode_Interrupt和事件EXTI_Mode_Event。第三个参数是触发方式,可以是下降沿触发EXTI_Trigger_Falling,上升沿触发EXTI_Trigger_Rising,或者任意电平(上升沿和下降沿)触发 EXTI_Trigger_Rising_Falling。 (3)优先级设置

设置好中断线和GPIO映射关系,然后又设置好了中断的触发模式等初始化参数。既然是外部中断,涉及到中断我们当然还要设置NVIC中断优先级。示例:

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能按键外部中断通道

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级2

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道

9

《嵌入式系统开发》0806504130 实验指导书

NVIC_Init(&NVIC_InitStructure); //中断优先级分组初始化 (4)中断服务函数

我们配置完中断优先级之后,接着要做的就是编写中断服务函数。中断服务函数的名字是在MDK中事先有定义的。这里需要说明一下,STM32的IO口外部中断函数只有6个,分别为:

EXPORT EXTI0_IRQHandler EXPORT EXTI1_IRQHandler EXPORT EXTI2_IRQHandler EXPORT EXTI3_IRQHandler EXPORT EXTI4_IRQHandler EXPORT EXTI9_5_IRQHandler EXPORT EXTI15_10_IRQHandler

中断线0-4每个中断线对应一个中断函数,中断线5-9共用中断函数EXTI9_5_IRQHandler,中断线10-15共用中断函数EXTI15_10_IRQHandler。在编写中断服务函数的时候会经常使用到两个函数,第一个函数是判断某个中断线上的中断是否发生(标志位是否置位):

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);

这个函数一般使用在中断服务函数的开头判断中断是否发生。另一个函数是清除某个中断线上的中断标志位:

void EXTI_ClearITPendingBit(uint32_t EXTI_Line);

这个函数一般应用在中断服务函数结束之前,清除中断标志位。 常用的中断服务函数格式为: void EXTI2_IRQHandler(void) {

if(EXTI_GetITStatus(EXTI_Line2)!=RESET)//判断某个线上的中断是否发生 {

中断逻辑…

EXTI_ClearITPendingBit(EXTI_Line2); //清除LINE上的中断标志位 } }

在这里需要说明一下,固件库还提供了两个函数用来判断外部中断状态以及清除外部状态标志位的函数EXTI_GetFlagStatus和EXTI_ClearFlag,他们的作用和前面两个函数的作用类似。只是在EXTI_GetITStatus函数中会先判断这种中断是否使能,使能了才去判断中断标志位,而EXTI_GetFlagStatus直接用来判断状态标志位。 (5)使用IO口外部中断的一般步骤:

1)初始化IO口为输入。

2)开启IO口复用时钟,设置IO口与中断线的映射关系。 3)初始化线上中断,设置触发条件等。 4)配置中断分组(NVIC),并使能中断。 5)编写中断服务函数。 3.5软件设计(学生完成)

完成中断函数exti.c、exti.h的编写。

提示:WK_UP(PA0)按键的中断检测, void EXTI0_IRQHandler(void)是外部中断0的服务函数,KEY0(PC5)按键的中断检测,void EXTI9_5_IRQHandler (void)是外部中断5~9的

10

《嵌入式系统开发》0806504130 实验指导书

服务函数;KEY1(PA15)按键的中断检测,void EXTI15_10_IRQHandler (void) 是外部中断10~15的服务函数。

编写:void EXTIX_Init(void) // 外部中断初始化函数 void EXTI0_IRQHandler(void) //中断0函数

void EXTI9_5_IRQHandler(void) //中断5函数 void EXTI15_10_IRQHandler(void) //中断15函数 (学生完成程序)

四、实验结果与分析

将调试结果的照片粘贴在这里。

11

《嵌入式系统开发》0806504130 实验指导书

实验四 PWM输出实验

实验时间:2016-04-26(周二3,4节),实验学时:2,实验地点:C105

一、实验目的与要求:

(1)掌握STM32定时器的结构

(2)掌握STM32中断配置的基本方法;

(2)使用STM32的定时器来产生PWM输出、改变占空比;

二、实验器材:

计算机,STM32F103RCT6实验平台。

三、实验过程

本实验用到的硬件资源有: 1) 指示灯DS0 2) 定时器TIM3

从TIM1_CH1通道和CH2通道的输出两列互补的20KHz的PWM波,从原理图(图6.2.1)可以看到,TIM1_CH1是和PA8复用的,而TIM1_CH2是和PA9复用的,占空比从0%-80%可调。

主要配置步骤如下:

1)开启TIM1时钟,使能PA时钟,配置PA8、PA9为复用输出。

要使用TIM1,我们必须先开启TIM1的时钟,还要配置PA8、PA9为复用输出(当然还要时能PORTA的时钟),这是因为TIM1_CH1、CH2通道将使用PA8、PA9的复用功能作为输出。库函数使能TIM1时钟的方法是:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能定时器1时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能GPIO外设时钟使能

设置PA8、PA9为复用功能输出的方法在前面的几个实验都有类似的讲解,这里简单列出GPIO初始化的一行代码即可:

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 2)设置TIM1的ARR和PSC。

在开启了TIM1的时钟之后,我们要设置ARR和PSC两个寄存器的值来控制输出PWM的周期。当PWM周期太慢(低于50Hz)的时候,我们就会明显感觉到闪烁了。因此,PWM周期在这里不宜设置的太小。这在库函数是通过TIM_TimeBaseInit函数实现的,在上一节定时器中断章节我们已经有讲解,这里就不详细讲解,调用的格式为:

TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值

12

《嵌入式系统开发》0806504130 实验指导书

TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式 TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的 3)设置TIM1_CH1、CH2的PWM模式及通道方向, 使能TIM1的CH1、CH2输出。

接下来,我们要设置TIM1_CH1、CH2为PWM模式(默认是冻结的),因为我们的DS0是低电平亮,而我们希望当CCR1的值小的时候,DS0就暗,CCR1值大的时候,DS0就亮,所以我们要通过配置TIM1_CCMR1的相关位来控制TIM1_CH1的模式。在库函数中,PWM通道设置是通过函数TIM_OC1Init()~TIM_OC4Init()来设置的,不同的通道的设置函数不一样,这里我们使用的是通道1、2,所以使用的函数是TIM_OC1Init()、TIM_OC2Init()。

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); 这种初始化格式大家学到这里应该也熟悉了,所以我们直接来看看结构体TIM_OCInitTypeDef的定义:

typedef struct {

uint16_t TIM_OCMode;

uint16_t TIM_OutputState; uint16_t TIM_OutputNState; */

uint16_t TIM_Pulse; uint16_t TIM_OCPolarity; uint16_t TIM_OCNPolarity; uint16_t TIM_OCIdleState; uint16_t TIM_OCNIdleState; } TIM_OCInitTypeDef;

这里我们讲解一下与我们要求相关的几个成员变量:

参数TIM_OCMode设置模式是PWM还是输出比较,这里我们是PWM模式。 参数TIM_OutputState用来设置比较输出使能,也就是使能PWM输出到端口。 参数TIM_OCPolarity用来设置极性是高还是低。

其他的参数TIM_OutputNState,TIM_OCNPolarity,TIM_OCIdleState和TIM_OCNIdleState是高级定时器TIM1和TIM8才用到的。

要实现我们上面提到的场景,方法是:

TIM_OCInitTypeDef TIM_OCInitStructure;

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择PWM模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高 TIM_OC1Init(TIM1, &TIM_OCInitStructure); //初始化TIM1 OC1 4)使能TIM1。

在完成以上设置了之后,我们需要使能TIM1。使能TIM1的方法前面已经讲解过: TIM_Cmd(TIM1, ENABLE); //使能TIM1 5)设置MOE输出,使能PWM输出。

普通定时器在完成以上设置了之后,就可以输出PWM了,但是高级定时器,我们还需要 使能刹车和死区寄存器(TIM1_BDTR)的MOE位,以使能整个OCx(即PWM)输出。库函数的设置函数为:

TIM_CtrlPWMOutputs(TIM1,ENABLE); // MOE主输出使能

13

《嵌入式系统开发》0806504130 实验指导书

TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1预装载使能 TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH2预装载使能 6)修改TIM1_CCR1来控制占空比。

最后,在经过以上设置之后,PWM 其实已经开始输出了,只是其占空比和频率都是固定的,而我们通过修改TIM1_CCR1则可以控制CH1的输出占空比。继而控制DS0的亮度。 在库函数中,修改TIM1_CCR1占空比的函数是:

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);

理所当然,对于其他通道,分别有一个函数名字,函数格式为TIM_SetComparex(x=1,2,3,4)。 通过以上6个步骤,我们就可以控制TIM1的CH1输出PWM波了。 软件设计(学生完成)

完成中断函数pwm.c、pwm.h及main.c的编写。 下载验证

在完成软件设计之后,将我们将编译好的文件下载到MiniSTM32开发板上,用示波器观看产生的CH1、CH2通道的波形。 四、实验结果与分析

1、将调试结果的示波器波形图粘贴在这里。 2、思考实现互补的PWM波形有哪两种方法? 方法一:在设置CH1

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; // TIM1脉冲宽度调制模式2 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //TIM输出比较极性高 在设置CH2时

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; // TIM输出比较极性低 方法二呢?

3.写出产生PWM频率为20kHz的设置方法:

f?72MHz/(arr?1)/(psc?1)

arr=? Psc=?

14

《嵌入式系统开发》0806504130 实验指导书

实验五 TFTLCD显示实验

实验时间:2016-05-03(周二3,4节),实验学时:2,实验地点:C105

一、实验目的与要求:

(1)掌握TFTLCD驱动的基本原理;

(2)掌握TFTLCD显示需要的相关设置步骤; (2)学会编写相应的驱动程序;

二、实验器材:

计算机,STM32F103RCT6实验平台。

三、实验过程

实验要求:将使用MiniSTM32开发板上的LCD接口,来点亮以2.8寸的、分辨率为320×240的TFTLCD模块,并实现ASCII字符和彩色的显示等功能,并在串口打印LCD控制器ID,同时在LCD每隔1s将屏幕底色依次变换为蓝、红、绿(LED0反转一次),同时在屏幕上显示以下内容。(三次后停止刷新底色,保持绿色底色,只有counter后面的数字变化) JIT.EDU.CN (起点坐标: 30,40,区域大小:200,24,字体大小24*12) TFTLCD TEST (起点坐标: 30,70,区域大小:200,16,字体大小16*8) C105 (起点坐标: 30,90,区域大小:200,16,字体大小16*8) lcd_id (起点坐标: 30,110,区域大小:200,16,字体大小16*8) counter: 44 这里的44是从0开始每隔1s加1 以上字符为红色。

1.硬件接口原理:

15

《嵌入式系统开发》0806504130 实验指导书

? LCD_CS(PC9):TFTLCD片选信号。 ? LCD _WR(PC7):向TFTLCD写入数据。 ? LCD _RD(PC6):从TFTLCD读取数据。

? LCD _D[15:0]( PB[15:0]):16位双向数据线。

? RST:硬复位TFTLCD,直接接到STM32的复位脚上,并不由软件控制; ? LCD _RS(PC8):命令/数据标志(0,读写命令;1,读写数据)。

TFTLCD模块采用16位的并方式与外部连接;采用ILI9341为液晶驱动器,ILI9341 采用RGB565格式存储颜色数据,此时ILI9341的18位数据线与MCU的16位数据线以及LCD GRAM的对应关系如图16.1.4所示:

从图中可以看出,ILI9341在16位模式下面,数据线有用的是:D17~D13和D11~D1,D0和D12没有用到,这样,ILI9341的D17~D13和D11~D1对应MCU的D15~D0。这样MCU的16位数据,最低5位代表蓝色,中间6位为绿色,最高5位为红色。数值越大,表示该颜色越深。另外,特别注意ILI9341所有的指令都是8位的(高8位无效),且参数除了读写GRAM的时候是16位,其他操作参数,都是8位的。

ILI9341的几个重要命令:0XD3,0X36,0X2A,0X2B,0X2C,0X2E等6条指令。 (1)0XD3,这个是读ID4指令,用于读取LCD控制器的ID;

(2)0X36,这是存储访问控制指令,可以控制ILI9341存储器的读写方向; (3)0X2A,这是列地址设置指令,在从左到右,从上到下的扫描方式(默认);

(4)0X2B,是页地址设置指令,在从左到右,从上到下的扫描方式(默认)下面,该指令用于设置纵坐标(y坐标);

(5)0X2C,该指令是写GRAM指令,在发送该指令之后,我们便可以往LCD的GRAM里面写入颜色数据了,该指令支持连续写;

(6)0X2E,该指令是读GRAM指令,用于读取ILI9341的显存(GRAM)。 2. TFTLCD显示需要的相关设置步骤:

1)设置STM32与TFTLCD模块相连接的IO。

先将我们与TFTLCD模块相连的IO口进行初始化,以便驱动LCD。 2)初始化TFTLCD模块

16

《嵌入式系统开发》0806504130 实验指导书

3)通过函数将字符和数字显示到TFTLCD模块上。 即:设置坐标,写GRAM指令,写GRAM来实现,但是这个步骤,只是一个点的处理,我们要显示字符/数字,就必须要多次使用这个步骤,从而达到显示字符/数字的目标;

刷新屏幕使用LCD_Clear()函数;

改变字体颜色使用POINT_COLOR()函数; 打印字符使用LCD_ShowString()函数; 打印数字使用LCD_ShowxNum()函数; 3.软件设计

根据设计要求,设计主函数main.c,将主函数写在这里。 四、实验结果与分析

将调试结果的照片粘贴在这里。

1. 串口打印的LCD控制器ID截图;2. 液晶屏幕的照片。

17

本文来源:https://www.bwwdw.com/article/7e46.html

Top