嵌入式实验报告

实验1  系统认识实验

一、实验目的

1.   了解Cortex-M3的GPIO使用及其相关的API函数;

2.   掌握Cortex-M3读取GPIO引脚状态的方法。

3.   掌握Cortex-M3的GPIO引脚输出控制的方法。

二、实验原理、内容及步骤

1.  实验原理

通用输入/输出端口GPIO模块可由多达9个物理GPIO模块组成,每个对应一个独立的GPIO端口。GPIO支持多达65个可编程的输入/输出引脚,具体数量取决于正在使用的器件型号。GPIO具有以下特性:

① 可编程控制GPIO中断,包括屏蔽中断发生、边沿触发(上升沿,下降沿,上升、下降沿)和高/低电平触发;

②  输入/输出可承受5V电压;

③  在读和写操作中通过地址线进行位屏蔽;

④  可编程控制GPIO引脚(pad)配置,包括弱上拉或下拉电阻、2mA/4mA/8mA引脚驱动、8mA驱动的斜率控制、开漏使能和数字输入使能。

数据控制寄存器允许用软件来配置GPIO的操作模式。数据方向寄存器将GPIO配置为输入或输出,而数据寄存器则捕获输入的数据或驱动数据从引脚输出。

GPIO方向GPIODIR(GPIO Direction)寄存器用来将每个独立的引脚配置为输入或输出。当数据方向设为0时,GPIO配置为输入,并且对应的数据寄存器位将捕获和储存GPIO端口上的值。当数据方向位设为1时,GPIO配置为输出,并且对应的数据寄存器位将在GPIO端口上输出。

为了提高软件的效率,通过将地址总线的位[9:2]用做屏蔽位,GPIO端口允许对GPIO数据GPIODATA(GPIO data)寄存器中的各个位进行修改。这样软件驱动程序仅使用一条指令就可以对各个GPIO引脚进行修改,而不会影响其它引脚的状态。为了提供这种特性寄存器GPIODATA覆盖了存储器映射中的256个位置。

默认情况下,除了用做JTAG/SWD功能的GPIO信号外,所有其他的GPIO信号都配置为非驱动(三态)。它们的数字功能被禁止,不驱动引脚上的逻辑值且不允许引脚电压进入GPIO接收器。为了使用引脚的数字功能(GPIO或复用功能),相应的GPIODEN位必须置位。

1)GPIO开关量输入

将GPIO连接数字开关量对应的管脚设置在输入状态;然后,写一个循环,不停地去检测输入引脚的状态。

2)GPIO输出驱动继电器(或光电隔离器)

将相关的GPIO设置成输出状态,并且要注意配置输出的驱动电流大小;然后,写一个循环,依次输出变化的高低电平,从而控制继电器及光电隔离器的关断与打开。

2.  创建新工程的步骤

1)创建一个目录,例如D:\DEMO

2)创建工作区,选择主菜单的File>New>Workspace命令,然后开启一个空白工作区窗口

3)生成新项目

  (1) 选择主菜单Project>Create New Project,弹出生成新项目窗口。选择Empty project 。

  (2) 在Tool chain栏中选择ARM,点击OK按钮,弹出另存为窗口。

  (3) 在“另存为”窗口中浏览和选择新建的D:\DEMO目录,输入新项目的文件名为demo,然后保存,这时在屏幕左边的Workspace窗口中将显示新建的项目名和输出代码模式。

4)保存工作区

5)添加/新建文件

 (1)建立文件组,右击“demo->Debug”然后选择ADD>ADD Group,新建三个文件组:startup文件组,src文件组 和lib文件组。

  (2) 向文件组添加对应文件(对应文件在相应目录中查找)

       ① 在lib组中添加driverlib.r79文件;

       ② 在startup组中添加startup.c文件;

       ③ 在src组中添加main.c文件或其他新建的 *.c文件。

3.  实验内容

1.  编程实现读取GPIO引脚上对应的开关量状态,改变开关量,观察能否成功读回;

2.  编程实现Cortex-M3的GPIO引脚驱动继电器及光电隔离器,观察继电器的动作以及发光管的亮灭变化;

1) 硬件电路如下(程序后面)

    2)程序如下

(1)系统初始化头文件systemInit.h

   #ifndef  SYSTEM_INIT_H

#define  SYSTEM_INIT_H

/*包含必要的头文件*/

#include <hw_types.h>

#include <hw_memmap.h>

#include <hw_ints.h>

#include <interrupt.h>

#include <sysctl.h>

#include <gpio.h>

/*声明全局的系统时钟变量*/

extern unsigned long TheSysClock;

/*系统时钟初始化*/

extern void clockInit(void);

#endif  // __SYSTEM_INIT_H__

(2)系统初始化实现文件systemInit.c

     #include  "systemInit.h"

/*定义全局的系统时钟变量*/

unsigned long TheSysClock = 12000000UL;

/*定义KEY*/

#define  KEY_PERIPH  SYSCTL_PERIPH_GPIOB

#define  KEY_PORT    GPIO_PORTB_BASE

#define  KEY_PIN     GPIO_PIN_5

/*系统时钟初始化*/

void clockInit(void) {

        SysCtlLDOSet(SYSCTL_LDO_2_50V);     //设置LDO输出电压

     SysCtlClockSet(SYSCTL_USE_OSC |     //系统时钟设置

                       SYSCTL_OSC_MAIN |    //采用主振荡器

                       SYSCTL_XTAL_6MHZ |   //外接6MHz晶振

                       SYSCTL_SYSDIV_1);    //不分频

        TheSysClock = SysCtlClockGet();     //获取当前的系统时钟频率

}

(3)主程序main.c

     #include "hw_types.h"

#include "hw_memmap.h"

#include "hw_gpio.h"

#include "systemInit.h"

#include "sysctl.h"

#define  DATA_PERIPH     SYSCTL_PERIPH_GPIOB  //定义PB口

#define  DATA_PORT_BASE  GPIO_PORTB_BASE   

#define  DATA_PORT_PIN   (GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|

GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7)

#define  DATA_PORT_BASE_PIN  DATA_PORT_BASE,DATA_PORT_PIN

#define  DATA_PORT           GPIOPinRead(DATA_PORT_BASE_PIN)

#define  OUT_PERIPH     SYSCTL_PERIPH_GPIOD  //定义PD口

#define  OUT_PORT_BASE  GPIO_PORTD_BASE   

#define  OUT_PORT_PIN   (GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|

GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5)

#define  OUT_PORT_BASE_PIN  OUT_PORT_BASE,OUT_PORT_PIN

#define  OUT2_PERIPH         SYSCTL_PERIPH_GPIOC //定义PC口

#define  OUT2_PORT_BASE      GPIO_PORTC_BASE   

#define  OUT2_PORT_PIN       GPIO_PIN_6|GPIO_PIN_7

#define  OUT2_PORT_BASE_PIN  OUT2_PORT_BASE,OUT2_PORT_PIN

void delay(unsigned int num) {

         unsigned int a;

         a=num;

         for(;a>0;a--);

}

int main(void){

 static char value;

        clockInit();

        SysCtlPeripheralEnable(DATA_PERIPH);     //使能相应的GPIO              

        GPIOPinTypeGPIOInput(DATA_PORT_BASE_PIN);//设置相应的数据管脚为输入

        SysCtlPeripheralEnable(OUT_PERIPH);      //使能相应的GPIO              

  GPIOPinTypeGPIOOutput(OUT_PORT_BASE_PIN); //设置相应的数据管脚为输入

    GPIOPadConfigSet(OUT_PORT_BASE,OUT_PORT_PIN,GPIO_STRENGTH_8MA,

                                                   GPIO_PIN_TYPE_STD_WPU);

   SysCtlPeripheralEnable(OUT2_PERIPH);      //使能相应的GPIO              

       GPIOPinTypeGPIOOutput(OUT2_PORT_BASE_PIN);//设置相应的数据管脚为输入

       GPIOPadConfigSet(OUT2_PORT_BASE,OUT2_PORT_PIN,GPIO_STRENGTH_8MA,

                                                     GPIO_PIN_TYPE_STD_WPU);

   while(1)              //无限循环

           value= DATA_PORT; //读数据口数值       

           delay(1000000);   //置断点,观察value值的变换

           GPIOPinWrite(OUT_PORT_BASE,OUT_PORT_PIN,value); 

           GPIOPinWrite(OUT2_PORT_BASE,OUT2_PORT_PIN,value);   

           delay(1000000);

       }

}

  (4)实验结果

当把可执行文件加载到硬件电路后,运行-按下按键,一段时间后继电器吸合,当断开按键后,一段时间后继电器打开。

  3)实验中存在的问题及处理方法

  (1)IAR软件安装问题

   刚接触IAR这个软件,在软件安装的过程中就出现了问题,在拷贝系统头文件(.h文件)和源文件(.c文件)的时候,由于文件较多,出现了漏拷文件的现象,所以在运行程序的时候总会报一些头文件找不到或打不开的错误。

解决办法:认真细心地重复拷一遍

(2)运行过程环境变量配置的问题

  由于环境变量配置比较多,所以在这个环节往往会出现环境变量漏配置的问题或配置错误,这会使程序无法运行

  解决办法:认真细心地一步一步地配置

4.  收获和体会

5.  思考题

1) GPIO的推挽输出和开漏输出在应用上有何区别?

推挽输出:可以输出高、低电平,连接数字器件

开漏输出:输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻才行,适合于做电流型的驱动,其吸收电流的能力相对强(一般20mA以内)。

开漏电路:就是指以MOSFET的漏极为输出的电路。一般的用法是会在漏极外部的电路添加上拉电阻。完整的开漏电路应该由开漏器件和开漏上来电阻组成。

2) 如何解决开漏模式下上拉电压不足的问题?

提高上拉电压或减小上拉电阻。

3)施密特触发输入有何作用?

                       实验2  定时器实验

一、实验目的

1.   了解Cortex-M3的定时/计数器使用及其相关的API函数;

2.   掌握Cortex-M3的定时/计数器使用方法与关键步骤;

3.   了解Cortex-M3的看门狗定时器使用及其相关的API函数;

4.   掌握Cortex-M3的看门狗定时器使用方法与关键步骤。

二、实验原理、内容及步骤

1.  实验原理

定时器是对固定频率脉冲进行计数,用计数值计算时间;而定时器是对外部输入脉冲计数。可编程定时器可驱动定时器输入引脚的外部事件进行计数或定时。Stellaris通用定时器模块GPTM(General-Purpose Timer Module)包含4个GPTM模块(定时器0、定时器1、定时器2和定时器3)。每个GPTM模块包含两个16位的定时器/计数器(称为TimerA和TimerB),用户可以将它们配置成独立运行的定时器或事件计数器,或将它们配置成1 个32 位定时器或一个32位实时时钟RTC(Real-Timer Clock)。定时器可用于触发模/数(A/D)转换等。可编程定时器支持一下模式:

☆ 32位定时器模式     单次触发定时器、周期(periodic)定时器和实时时钟;

☆ 16位定时器模式     单次触发(one-shot)定时器和周期定时器;

☆ 16位输入捕获模式   输入边沿计数捕获和输入边沿定时捕获;

☆ 16位PWM(Pulse-Width Modulation)模式。

1)计数器实验

首先,将相应的定时/计数器配置好(使能,计数初值的装载等);然后,注册相应的中断,编写中断服务程序;最后,使能中断,进入一个死循环中,当计数满5次后,计数器溢出,触发标志位,产生中断,进入到中断服务程序中执行。

2)秒时钟发生器实验

首先,将相应的定时/计数器配置好(使能,定时初值的装载等);然后,注册相应的中断,编写中断服务程序;最后,使能中断,进入一个死循环中,当定时时间到后,产生中断,进入到中断服务程序中执行。

3)看门狗定时器实验

首先,使能看门狗定时器的定时功能,装载初值;然后,注册相应的中断,编写中断服务程序;最后,使能中断,进入一个死循环中,当时间到后,产生中断,进入到中断服务程序中执行,即翻转一个GPIO引脚电平,产生方波输出。

3.  实验内容

1)计数器实验

编程实现利用Cortex-M3的定时/计数器引脚对外部脉冲进行计数,每计数满5个后产生计数中断。

(1)   硬件电路如下

(2)   程序如下:

    ① 头文件systemInit.h

       #ifndef  __SYSTEM_INIT_H__

#define  __SYSTEM_INIT_H__

/*包含必要的头文件*/

#include <hw_types.h>

#include <hw_memmap.h>

#include <hw_ints.h>

#include <interrupt.h>

#include <sysctl.h>

#include <gpio.h>

/*声明全局的系统时钟变量*/

extern unsigned long TheSysClock;

/*系统时钟初始化*/

extern void clockInit(void);

#endif  // __SYSTEM_INIT_H__

 ② 实现文件systemInit.c

      #include  "systemInit.h"

/*定义全局的系统时钟变量*/

unsigned long TheSysClock = 12000000UL;

/*定义KEY*/

#define  KEY_PERIPH  SYSCTL_PERIPH_GPIOB

#define  KEY_PORT    GPIO_PORTB_BASE

#define  KEY_PIN     GPIO_PIN_5

/*系统时钟初始化*/

void clockInit(void) {

    SysCtlLDOSet(SYSCTL_LDO_2_50V);           //设置LDO输出电压

              SysCtlClockSet(SYSCTL_USE_OSC |      //系统时钟设置

                             SYSCTL_OSC_MAIN |     //采用主振荡器

                             SYSCTL_XTAL_6MHZ |    //外接6MHz晶振

                             SYSCTL_SYSDIV_1);     //不分频

              TheSysClock = SysCtlClockGet();      //获取当前的系统时钟频率

}

       ③ 主程序main.c

      #include "hw_types.h"

#include "hw_memmap.h"

#include "hw_gpio.h"

#include "systemInit.h"

#include "sysctl.h"

#include "hw_ints.h"

#include "gpio.h"

#include "systick.h"

#include "timer.h"

#include "interrupt.h"

#define  KEY_PERIPH         SYSCTL_PERIPH_GPIOD  //定义PD口

#define  KEY_PORT_BASE      GPIO_PORTD_BASE   

#define  KEY                GPIO_PIN_4

#define  LED_PERIPH         SYSCTL_PERIPH_GPIOD  //定义PC口

#define  LED_PORT_BASE      GPIO_PORTD_BASE   

#define  LED                GPIO_PIN_0

#define  LED_PORT_BASE_PIN  LED_PORT_BASE,LED

/*定时器16位输入边沿计数捕获功能初始化*/

void timerInitCapCount(void)  {

  SysCtlPeripheralEnable(KEY_PERIPH);

          GPIOPinTypeTimer(KEY_PORT_BASE, KEY);//配置CCP0管脚为脉冲输入

          SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);//使能Timer模块

          TimerConfigure(TIMER0_BASE,

TIMER_CFG_16_BIT_PAIR | //配置Timer为16位事件计数器

                         TIMER_CFG_A_CAP_COUNT);

 TimerControlEvent(TIMER0_BASE,         //控制TimerA捕获CCP负边沿

                           TIMER_A,TIMER_EVENT_NEG_EDGE);

TimerLoadSet(TIMER0_BASE, TIMER_A, 10);  //设置计数器初值

TimerMatchSet(TIMER0_BASE, TIMER_A, 5);  //设置事件计数匹配值

TimerIntEnable(TIMER0_BASE, TIMER_CAPA_MATCH);//使能TimerA捕获匹配中断

        IntEnable(INT_TIMER0A);//能Timer中断

        IntMasterEnable( );//使能处理器中断

   TimerEnable(TIMER0_BASE, TIMER_A);//使能Timer计数

}

void Timer0A_ISR(void) {  //计数器中断

   TimerIntClear(TIMER0_BASE, TIMER_CAPA_MATCH);//清除定时器0中断。

   TimerLoadSet(TIMER0_BASE, TIMER_A, 10);//重装定时器装载值为10

                   GPIOPinWrite(LED_PORT_BASE,LED, GPIOPinRead(LED_PORT_BASE,LED)^LED);//翻转LED端口。

   TimerEnable(TIMER0_BASE, TIMER_A);//使能定时器0。

}

int main(void) {

   clockInit();

          timerInitCapCount();   

   Timer0A_ISR(); 

      SysCtlPeripheralEnable(LED_PERIPH);//使能相应的GPIO              

          GPIOPinTypeGPIOOutput(LED_PORT_BASE_PIN);//设置相应的数据管脚为输出

   GPIOPadConfigSet(LED_PORT_BASE,LED,GPIO_STRENGTH_8MA,                                                                                     GPIO_PIN_TYPE_STD_WPU);

   while(1) ;  //无限循环

}

2)秒时钟发生器实验

编程实现利用Cortex-M3的定时/计数器的精确定时功能,产生一个频率为1Hz的时钟输出。

(1)   硬件电路如下:

(2)   程序如下:

     ① 系统初始化头文件systemInit.h

        #ifndef  __SYSTEM_INIT_H__

#define  __SYSTEM_INIT_H__

/*包含必要的头文件*/

#include <hw_types.h>

#include <hw_memmap.h>

#include <hw_ints.h>

#include <interrupt.h>

#include <sysctl.h>

#include <gpio.h>

/*声明全局的系统时钟变量*/

extern unsigned long TheSysClock;

/*系统时钟初始化*/

extern void clockInit(void);

#endif  //  __SYSTEM_INIT_H__

     ② 系统初始化实现文件systemInit.c

       #include  "systemInit.h"

/*定义全局的系统时钟变量*/

unsigned long TheSysClock = 12000000UL;

/*定义KEY*/

#define  KEY_PERIPH    SYSCTL_PERIPH_GPIOB

#define  KEY_PORT        GPIO_PORTB_BASE

#define  KEY_PIN           GPIO_PIN_5

/*系统时钟初始化*/

void clockInit(void)  {

           SysCtlLDOSet(SYSCTL_LDO_2_50V);      //设置LDO输出电压

           SysCtlClockSet(SYSCTL_USE_OSC |      //系统时钟设置

                          SYSCTL_OSC_MAIN |     //  采用主振荡器

                          SYSCTL_XTAL_6MHZ |    //外接6MHz晶振

                          SYSCTL_SYSDIV_1);     // 不分频

   TheSysClock = SysCtlClockGet();   // 获取当前的系统时钟频率

}

     ③ 主程序main.c

     #include  "hw_types.h"

#include  "hw_memmap.h"

#include  "hw_gpio.h"

#include  "systemInit.h"

#include  "sysctl.h"

#include  "hw_ints.h"

#include  "gpio.h"

#include  "systick.h"

#include  "timer.h"

#include  "interrupt.h"

#define  LED_PERIPH          SYSCTL_PERIPH_GPIOD     //定义PC口

#define  LED_PORT_BASE       GPIO_PORTD_BASE   

#define  LED                 GPIO_PIN_0

#define  LED_PORT_BASE_PIN   LED_PORT_BASE_LED

void Timer0A_ISR(void)  { //计数器中断

         TimerIntClear( TIMER0_BASE, TIMER_CAPA_MATCH );//清除定时器0中断

GPIOPinWrite(LED_PORT_BASE,LED,GPIOPinRead(LED_PORT_BASE,LED)^LED);//翻转LED 端

         TimerEnable(TIMER0_BASE, TIMER_A); //使能定时器0

}

int main(void)  {

clockInit();

SysCtlPeripheralEnable( SYSCTL_PERIPH_TIMER0 );    

TimerConfigure(TIMER0_BASE,TIMER_CFG_32_BIT_PER);//设置定时器0为周期触发模TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet());//设置定时器装载值:定时1秒TimerIntEnable(TIMER0_BASE,TIMER_TIMA_TIMEOUT);//设置定时器为溢出中断

TimerEnable(TIMER0_BASE, TIMER_A);//使能定时器0

IntEnable(INT_TIMER0A);//使能定时器0外设

IntMasterEnable();                         SysCtlPeripheralEnable(LED_PERIPH);//使能相应的GPIO                                                        GPIOPinTypeGPIOOutput(LED_PORT_BASE_PIN);//设置相应的数据管脚为输出    GPIOPadConfigSet(LED_PORT_BASE,LED,GPIO_STRENGTH_8MA,                                                                                                              

GPIO_PIN_TYPE_STD_WPU );

while(1); //无限循环

}

3)看门狗定时器实验

编程实现利用Cortex-M3的看门狗定时器功能,产生一个方波输出。

(1)   硬件电路同2)

(2)   程序如下:

   ① 系统初始化头文件systemInit.h

     #ifndef  __SYSTEM_INIT_H__

#define  __SYSTEM_INIT_H__

/*包含必要的头文件*/

#include  <hw_types.h>

#include  <hw_memmap.h>

#include  <hw_ints.h>

#include  <interrupt.h>

#include  <sysctl.h>

#include  <gpio.h>

/*声明全局的系统时钟变量*/

extern unsigned long TheSysClock;

/*系统时钟初始化*/

extern void clockInit(void);

#endif  //  __SYSTEM_INIT_H__

   ② 系统初始化实现文件systemInit.c

     #include  "systemInit.h"

/*定义全局的系统时钟变量*/

unsigned long TheSysClock = 12000000UL;

/*定义KEY*/

#define  KEY_PERIPH  SYSCTL_PERIPH_GPIOB

#define  KEY_PORT    GPIO_PORTB_BASE

#define  KEY_PIN     GPIO_PIN_5

/*系统时钟初始化*/

void clockInit(void) {

        SysCtlLDOSet(SYSCTL_LDO_2_50V);    //设置LDO输出电压

            SysCtlClockSet(SYSCTL_USE_OSC |      //系统时钟设置

                           SYSCTL_OSC_MAIN |     //采用主振荡器

                           SYSCTL_XTAL_6MHZ |    //外接6MHz晶振

                           SYSCTL_SYSDIV_1);     //不分频

       TheSysClock = SysCtlClockGet();      //  获取当前的系统时钟频率

}

 ③ 主程序mian.c

 #include  "systemInit.h"

#include  "watchdog.h"

/*定义LED*/

#define  LED_PERIPH   SYSCTL_PERIPH_GPIOD

#define  LED_PORT     GPIO_PORTD_BASE

#define  LED_PIN      GPIO_PIN_0

#define  LED_PIN1     GPIO_PIN_1

/*LED初始化*/

void ledInit(void)  {

   SysCtlPeripheralEnable(LED_PERIPH);//使能LED所在的GPIO端口

   GPIOPinTypeGPIOOutput(LED_PORT, LED_PIN|LED_PIN1);//设置LED所在管脚为输出

   GPIOPinWrite(LED_PORT, LED_PIN, 0xFF);//熄灭LED

}

/*看门狗初始化*/

void wdogInit(void)  {

    unsigned long ulValue = 350*(TheSysClock/1000);//准备定时350ms

    SysCtlPeripheralEnable(SYSCTL_PERIPH_WDOG);//使能看门狗模块

    WatchdogResetEnable(WATCHDOG_BASE);//使能看门狗复位功能

    WatchdogStallEnable(WATCHDOG_BASE);//使能调试器暂停看门狗计数

    WatchdogReloadSet(WATCHDOG_BASE, ulValue);//设置看门狗装载值

    WatchdogIntEnable(WATCHDOG_BASE);//使能看门狗中断

    IntEnable(INT_WATCHDOG);//使能看门狗模块中断

    IntMasterEnable();//使能处理器中断

    WatchdogEnable(WATCHDOG_BASE);//使能看门狗

    WatchdogLock(WATCHDOG_BASE);//锁定看门狗          

}

void delay(unsigned int num)  {

       unsigned int a;

       a=num;

        for(;a>0;a--);

}

void WatchdogFeed(void)  {  //喂狗程序

       WatchdogUnlock(WATCHDOG_BASE);//解锁

       WatchdogIntClear(WATCHDOG_BASE);//清除中断状态,重要!

      WatchdogLock(WATCHDOG_BASE);//锁定

       GPIOPinWrite(LED_PORT,LED_PIN,0x00);//LED_PIN 引脚输出0(点亮LED)

       delay(10000);//延时

GPIOPinWrite(LED_PORT,LED_PIN,0xFF);//LED_PIN 引脚输出1(熄灭LED)

}

int main(void) {

      clockInit();//时钟初始化:晶振,6MHz

      ledInit(); //LED初始化

      GPIOPinWrite(LED_PORT, LED_PIN1, 0x00);//熄灭LED

   delay(100000);

      GPIOPinWrite(LED_PORT, LED_PIN1, 0xFF);//熄灭LED

   delay(100000);

      wdogInit();//看门狗初始化

    for (;;)  {

          WatchdogFeed();

         delay(100000);//喂狗间隔可保证不会出现复位

      }

}

(3)实验中存在的问题及处理方法

运行过程环境变量配置的问题

  由于环境变量配置比较多,所以在这个环节往往会出现环境变量漏配置的问题或配置错误,这会使程序无法运行

  解决办法:认真细心地一步一步地配置

4.  收获和体会

4.  思考题

1)如何得到其它时间(如:2s、3s等)的定时。

     有如下语句:unsigned long ulValue = n*(TheSysClock/1000); 若要定时2s则令n=2000,同理若要定时3s则令n=3000。再用函数库void TimerLoadSet(unsigned long ulBase, unsigned long  ulTimer, unsigned long ulValue);中的第三个参数来调用即可。

3) 计数器的初值是如何得到的,中断的注册是如何完成的。

根据需要可设置计数器的初值;中断的注册可通过另设置一中断服务程序(函数),可通过调用相关库函数并设置相关参数来完成注册。

                    实验3  PWM发生器实验

一、实验目的

1.   了解Cortex-M3的PWM使用及其相关的API函数;

2.   掌握Cortex-M3的PWM使用的方法与步骤。

二、实验原理、内容及步骤

1.  实验原理

脉宽调制PWM(Pulse Width Modulation)是一项功能强大的技术,是一种对模拟信号电平进行数字化编码的方法。在脉冲调制中使用高分辨率计数器来产生方波,并且可以通过调整方波的占空比来对模拟信号电平进行编码。PWM通常使用在开关电源(switching power)和电机控制中。

Stellaris  PWM模块由1到4个PWM发生器模块和1个控制模块组成。每个PWM发生器模块包含1个定时器(16位递减或先递增后递减计数器)、2个PWM比较器、PWM信号发生器(可产生8个独立的PWM信号)、死区发生器(可产生4对带死区延时的PWM信号)和中断/ADC触发选择器。而控制模块决定了PWM信号的极性,以及将哪个信号传递到引脚。

每个PWM发生器模块产生2个PWM信号。这2个PWM信号共享同一定时器和频率,可以编程为独立的信号,也可以编程为一对插入死区的延迟的互补(complement)信号。这些PWM发生模块的输出信号在传递到器件引脚之前,由输出控制模块管理。

配置PWM相关的控制参数,使能PWM外设,设定源时钟和比较寄存器以及死区寄存器,设置占空比,最后使能PWM发生器。

2.  实验内容

编程配置Cortex-M3的PWM功能参数,输出一定占空比的PWM波形。

(1)   硬件电路如下

(2)   程序如下:

① 系统初始化头文件systemInit.h

  #ifndef  __SYSTEM_INIT_H__

#define  __SYSTEM_INIT_H__

/*包含必要的头文件*/

#include  <hw_types.h>

#include  <hw_memmap.h>

#include  <hw_ints.h>

#include  <interrupt.h>

#include  <sysctl.h>

#include  <gpio.h>

/*声明全局的系统时钟变量*/

extern unsigned long TheSysClock;

/*系统时钟初始化*/

extern void clockInit(void);

#endif  //  __SYSTEM_INIT_H__

   ② 系统初始化实现文件systemInit.c

      #include  "systemInit.h"

/*定义全局的系统时钟变量*/

unsigned long TheSysClock = 12000000UL;

/*定义KEY*/

#define  KEY_PERIPH  SYSCTL_PERIPH_GPIOB

#define  KEY_PORT    GPIO_PORTB_BASE

#define  KEY_PIN     GPIO_PIN_5

/*系统时钟初始化*/

void clockInit(void) {

    SysCtlLDOSet(SYSCTL_LDO_2_50V);     //设置LDO输出电压

           SysCtlClockSet(SYSCTL_USE_OSC |     //系统时钟设置

                          SYSCTL_OSC_MAIN |    //采用主振荡器

                          SYSCTL_XTAL_6MHZ |   //外接6MHz晶振

                          SYSCTL_SYSDIV_1);    //不分频

           TheSysClock = SysCtlClockGet();    //获取当前的系统时钟频率

}

  ③ 主函数mian.c

     /*过程:上电全速运行程序,用示波器观察PWM0或PWM1插孔的波形*/

#include  "hw_types.h"

#include  "hw_memmap.h"

#include  "hw_ints.h"

#include  "hw_gpio.h"

#include  "hw_pwm.h"

#include  <sysctl.h>

#include  "systick.h"

#include  "debug.h"

#include  "gpio.h"

#include  "pwm.h"

#include  "systeminit.h"

int main(void) {

         clockInit();

         SysCtlPWMClockSet(SYSCTL_PWMDIV_1);//PWM时钟源1分频   

         SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);//使能PD口外设

         SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM);//使能PWM外设

    /*设置PD0,PD1为PWM0和PWM1*/

         GPIOPinTypePWM(GPIO_PORTD_BASE,GPIO_PIN_0|GPIO_PIN_1);

/*设置PWM发生器0为上下计数方式,两路PWM不同步 */

PWMGenConfigure(PWM_BASE,PWM_GEN_0,PWM_GEN_MODE_UP_DOWN|

PWM_GEN_MODE_NO_SYNC);

PWMGenPeriodSet(PWM_BASE,PWM_GEN_0,60000);//设置两路PWM的共同周期

PWMPulseWidthSet(PWM_BASE,PWM_OUT_0,40000); //分别设置两路PWM的匹配值

PWMPulseWidthSet(PWM_BASE,PWM_OUT_1,20000); //修改50000和10000可以设置占空比

/*使能PWM0和PWM1*/

        PWMOutputState(PWM_BASE,PWM_OUT_0_BIT|PWM_OUT_1_BIT,true);   PWMGenEnable(PWM_BASE, PWM_GEN_0);//使能PWM发生器0

        while(1);

}

4) 实验中遇到的问题及处理办法

参看实验二

3.  收获与体会

4.   

5.  思考题

1)PWM发生器模块包括哪些部件,每个部件的作用是什么?

        PWM发生器模块由以下部件组成:

(1) PWM定时器:用于计数(递减计数或先递增后递减计数);

(2) PWM比较器:每个PWM发生器含两个比较器,用于监控计数器的值。当比较器的值与计数器的值相等时,比较器会输出一个宽度为单个时钟周期的高电平脉冲;

(3) PWM信号发生器:作为高低电平驱动信号;

(4) 死区发生器:产生时间延迟;

(5) 中断/ADC触发选择器:产生中断或ADC触发信号。

2) PWM控制器模块的作用是什么?

PWM控制器模块决定了PWM信号的极性,以及将哪个信号传递到引脚。

3) Stellaris系列ARM的PWM模块可用于哪些场合?

Stellaris系列ARM的PWM模块通常使用在开关电源(switching power)和电机控制中。

   实验三  PWM实验电路图

实验结果:

          实验二

2- 1)计数器实验电路图

          2- 2)秒时钟发生器实验电路图

          2- 3)看门狗定时器实验电路图

实验4  16*16 LED点阵显示汉字实验电路图

实验4  16*16 LED点阵显示汉字实验

一、实验目的

1.学习Cortex-M3的GPIO使用及其相关的API函数;

2.掌握16*16 LED点阵显示汉字的原理及其控制方法。

二、实验原理、内容及步骤

1.  实验原理

该模块主要显示汉字的功能。采用两片74LS138控制行信号,两片74LS595传送数据,实现串入并出的的方式,这样可以节省MCU的GPIO口。74LS138控制的行给低电平,数据位给高电平的时候对应的点会点亮。

配置Cortex-M3的GPIO端口,用GPIO端口控制74LS138译码产生16位行选通信号,控制74HC595(串转并的方式)传送16位的显示数据。

2.  实验内容

用Cortex-M3的GPIO控制74LS138和74HC595,即控制行、列扫信号,来驱动16X16 LED点阵显示多个不同的汉字。

1) 硬件电路如下:

2) 程序如下:

(1)   系统初始化头文件systemInit.h

          #ifndef  __SYSTEM_INIT_H__

#define  __SYSTEM_INIT_H__

/*包含必要的头文件*/

#include  <hw_types.h>

#include  <hw_memmap.h>

#include  <hw_ints.h>

#include  <interrupt.h>

#include  <sysctl.h>

#include  <gpio.h>

/*声明全局的系统时钟变量*/

extern unsigned long TheSysClock;

/*系统时钟初始化*/

extern void clockInit(void);

#endif  //  __SYSTEM_INIT_H__

(2)   系统初始化实现文件systemInit.c

          #include  "systemInit.h"

/*定义全局的系统时钟变量*/

unsigned long TheSysClock = 12000000UL;

/*定义KEY*/

#define  KEY_PERIPH    SYSCTL_PERIPH_GPIOB

#define  KEY_PORT        GPIO_PORTB_BASE

#define  KEY_PIN           GPIO_PIN_5

/*系统时钟初始化*/

void clockInit(void)  {

             SysCtlLDOSet(SYSCTL_LDO_2_50V);    //设置LDO输出电压

        SysCtlClockSet(SYSCTL_USE_OSC|    //系统时钟设置

                            SYSCTL_OSC_MAIN|   //采用主振荡器

                            SYSCTL_XTAL_6MHZ|  //外接6MHz晶振

                            SYSCTL_SYSDIV_1);  //不分频

            TheSysClock = SysCtlClockGet();    //获取当前的系统时钟频率

}

(3)   主程序main.c

     /*

接线:

1、用导线将MCU的MCU_IO1---MCU_IO4分别连接到16*16LED的A0、A1、A2、A3。

2、用导线将MCU的MCU_IO9---MCU_IO11分别连接到16*16LED的SHCR、STCP、DS。

3、将CPU板上的跳线帽JP1--JP8短接在左侧。

过程:

上电,编译、下载程序,观察16*16LED上显示的内容。

*/

#include  "systemInit.h"

#include  "hw_memmap.h"                                   

#include  "hw_types.h"

#include  "hw_ints.h"

#include  "sysctl.h"

#include  "systick.h"

#include  "hw_gpio.h"

#define uchar unsigned char

#define uint unsigned int

unsigned char table[] = {

0x01,0x00,0x00,0x80,0x3F,0xFE,0x20,0x80,0x2F,0xF8,0x20,0x88,0x3F,0xFE,0x20,0x88,

0x2F,0xF8,0x28,0x80,0x24,0xC8,0x22,0xD8,0x24,0xA0,0x58,0x98,0x4A,0x8E,0x81,0x04/*"康",0*/

};   

#define  LED_PERIPH       SYSCTL_PERIPH_GPIOD |SYSCTL_PERIPH_GPIOA

#define  LED_SHCP_BASE    GPIO_PORTA_BASE      // SHCP - PE0                    

#define  LED_SHCP_PIN     GPIO_PIN_0

#define  LED_STCP_BASE    GPIO_PORTA_BASE      // STCP - PE1                    

#define  LED_STCP_PIN     GPIO_PIN_1

#define  LED_DS_BASE      GPIO_PORTA_BASE      // DS - PE2                  

#define  LED_DS_PIN       GPIO_PIN_2

#define  DATA_PORT_BASE   GPIO_PORTD_BASE      // DATA[7:0] - PD[7:0]         

#define  DATA_PORT_PIN    0xFF

/*硬件相关的定义*/

#define  LED_SHCP_BASE_PIN   LED_SHCP_BASE,LED_SHCP_PIN

#define  LED_STCP_BASE_PIN   LED_STCP_BASE,LED_STCP_PIN

#define  LED_DS_BASE_PIN     LED_DS_BASE,  LED_DS_PIN

#define  DATA_PORT_BASE_PIN  DATA_PORT_BASE,DATA_PORT_PIN

/*硬件相关的位操作定义*/

#define  LED_SHCP   HWREG(LED_SHCP_BASE+(GPIO_O_DATA+(LED_SHCP_PIN<<2)))

#define  LED_STCP   HWREG(LED_STCP_BASE+(GPIO_O_DATA+(LED_STCP_PIN<<2)))

#define  LED_DS     HWREG(LED_DS_BASE +(GPIO_O_DATA + (LED_DS_PIN << 2)))

#define  DATA_PORT  HWREG(DATA_PORT_BASE+(GPIO_O_DATA+(DATA_PORT_PIN<<2)))

/*设置数据口为输出方向*/     

#define  DATA_PROT_OUTPUT_SET()  HWREG(DATA_PORT_BASE+GPIO_O_DIR)= 0xFF

/*SHCP管脚为低*/                                       

#define  SHCP_L  GPIOPinWrite(LED_SHCP_BASE ,LED_SHCP_PIN,0x00);      

/*STCP管脚为低*/

#define  STCP_L  GPIOPinWrite(LED_STCP_BASE ,LED_STCP_PIN,0x00); 

 #define  DS_L    GPIOPinWrite(LED_DS_BASE ,  LED_DS_PIN,0x00);//DS管脚为低

/*SHCP管脚为高*/

#define  SHCP_H  GPIOPinWrite(LED_SHCP_BASE ,LED_SHCP_PIN,0xFF);//STCP管脚为高

#define  STCP_H  GPIOPinWrite(LED_STCP_BASE ,LED_STCP_PIN,0xFF);

#define  DS_H    GPIOPinWrite(LED_DS_BASE ,  LED_DS_PIN,0xFF);//DS管脚为高

void delay(unsigned int count) {

unsigned int a;

    for(a=count;a>0;a--);

}

void init(void)  {

clockInit();

SysCtlPeripheralEnable(LED_PERIPH);        // 使能相应的GPIO              

    GPIOPinTypeGPIOOutput(LED_SHCP_BASE_PIN);  // 设置相应的控制管脚为输出    

    GPIOPinTypeGPIOOutput(LED_STCP_BASE_PIN);  // 设置相应的控制管脚为输出    

    GPIOPinTypeGPIOOutput(LED_DS_BASE_PIN);    // 设置相应的控制管脚为输出    

 GPIOPinTypeGPIOOutput(DATA_PORT_BASE_PIN); // 设置相应的数据管脚为输出    

 /*配置数据端口为8mA,若上拉输出*/

GPIOPadConfigSet(DATA_PORT_BASE,  LED_SHCP_PIN |

                     LED_STCP_PIN | LED_DS_PIN |DATA_PORT_PIN ,

GPIO_STRENGTH_8MA,GPIO_PIN_TYPE_STD_WPU);       

DATA_PORT=0xFF;

SHCP_H;

STCP_H;

DS_H;

}

void WriteByte(unsigned char dat) {  //写一个字节的数据

      unsigned char  i,x=0;

      for(i=0;i<8;i++) {    //循环8次把编码传给锁存器

           x=dat&0x1

          SHCP_L;

          if(x==0) {

              DS_L;

           }else {

              DS_H;

           }

dat=dat>>1;      //右移一位,取出该字节的最低位

           SHCP_H;             

}    

}

void disp(unsigned char *p)  {

unsigned int num,i,temp[32];

         for(i=0;i<32;i++)  {

             temp[i]=*p++;

         }

         for(i=0;i<32;i++)  {

             for(num=0;num<16;num++)  { 

 WriteByte(temp[2*num]);  //送出一个字节 

WriteByte(temp[2*num+1]);

                 STCP_L;//STCP_H;输出锁存器中的数据,下降沿

DATA_PORT=num;   //行选

                 STCP_H;//STCP_L;

                 delay(1000);

 }

 }

}

int main(void)  {   

          init();

          while(1)  {     

              disp(table); //显示“康”

          }      

}

3) 实验中存在的问题及处理方法

参考实验二

3.  收获和体会

4.  思考题

1.   简述LED点阵显示汉字的原理。

 该模块主要显示汉字的功能。采用两片74LS138控制行信号,两片74LS595传送数据,实现串入并出的的方式,这样可以节省MCU的GPIO口。74LS138控制的行给低电平,数据位给高电平的时候对应的点会点亮。

相关推荐