嵌入式导论综合实验设计——嵌入式期末报告
TM4C123GXL Final Project
实验题目
综合实验设计
实验目的和要求
进一步掌握本学期以来所做实验用到的各种元器件的使用方法和编程;
加深GPIO、中断、定时器、LED等的使用;
加强综合问题解决能力和拓展思维创新能力。
设计思路
使用嵌入式导论实验课所学的知识进行期末综合实验的设计。
使用串口使开发板与主机通信。从主机输入颜色字符串 RED、BLUE、GREE、YELLOW、LBLUE、PURPLE、WHITE
开发板接收通信数据后,LED相应的显示指示的颜色。通过对按钮不同的操作,通过选择不同的时钟频率,改变LED灯闪动的频率。
实现功能
- 串口通信
- 使用外部触发中断产生按钮状态改变响应
- 使用查询方式检查按钮状态
- 设置灯的多种变换模式、变化速度
使用工具
- Keil version5
- Serial Port Utility串口调试助手
- TM4C123GXL开发板
程序流程图
实际运行
blue.png
shinning.png
green.png
purple.png
设计分析体会
实验体会:
本次期末综合性实验,把前面所学的实验知识做了合并,灵活运用所学知识,实现 串口通信、使用外部触发中断产生按钮状态改变响应、使用查询方式检查按钮状态、设置灯的多种变换模式、变化速度等功能。对开发软件keil的debug功能掌握了很多操作,使得做实验效率更高。
重要模块1:定义颜色
#define RED 0x02
#define BLUE 0x04
#define GREEN 0x08
#define YELLOW 0x0A
#define LBLUE 0x0C
#define PURPLE 0x06
#define WHITE 0x0E
#define DARK 0x00
#define WHEELSIZE 2 //轮转大小
//定义轮转颜色数组
const long COLORWHEEL1[WHEELSIZE] = {RED, 0};
const long COLORWHEEL2[WHEELSIZE] = {BLUE, 0};
const long COLORWHEEL3[WHEELSIZE] = {GREEN, 0};
const long COLORWHEEL4[WHEELSIZE] = {YELLOW, 0};
const long COLORWHEEL5[WHEELSIZE] = {LBLUE, 0};
const long COLORWHEEL6[WHEELSIZE] = {PURPLE, 0};
const long COLORWHEEL7[WHEELSIZE] = {WHITE, 0};
重要模块2:定义回调函数,响应串口动作
//定义回调函数
//根据串口的输入的不同,选择颜色进行闪烁
void UserTask(void){
static int i = 0;
if(choose==1)
{
LEDS = COLORWHEEL1[i];
}
else if(choose==2)
{
LEDS = COLORWHEEL2[i];
}
else if(choose==3)
{
LEDS = COLORWHEEL3[i];
}
else if(choose==4)
{
LEDS = COLORWHEEL4[i];
}
else if(choose==5)
{
LEDS = COLORWHEEL5[i];
}
else if(choose==6)
{
LEDS = COLORWHEEL6[i];
}
else if(choose==7)
{
LEDS = COLORWHEEL7[i];
}
i = i + 1;
if(i==2)
{
i=0;
}
}
重要模块3:定义改变LED闪烁频率函数,通过时钟频率的不同,改变LED闪烁的快慢
//定义调用UserTask回调函数的频率
#define F20KHZ (50000000/20000)
#define F16HZ (50000000/16)
#define F8HZ (50000000/8)
#define F4HZ (50000000/4)
#define F2HZ (50000000/2)
#define F1HZ (50000000)
//设置LED等闪烁的频率
void set_LED_rate(uint32_t rate){
switch(rate){
case 1:
Timer0A_Init(&UserTask, F1HZ);
break;
case 2:
Timer0A_Init(&UserTask, F2HZ);
break;
case 3:
Timer0A_Init(&UserTask, F4HZ);
break;
case 4:
Timer0A_Init(&UserTask, F8HZ);
break;
case 5:
Timer0A_Init(&UserTask, F16HZ);
break;
}
}
重要模块4:设计PortF外部中断动作
//使用外部中断 ,按钮SW1按下即触发
//调用设置led频率的函数,使闪烁频率变快
void GPIOPortF_Handler(void){ //sw1 press
GPIO_PORTF_ICR_R = 0x10;// acknowledge flag0
FallingEdges = 5;
set_LED_rate(FallingEdges);
}
重要模块5:设计按钮在查询模式下的动作
//使用查询模式
//通过循环不断的判断按钮的状态,两个按钮之一被按下、同时被按下、都不被按下
while(1){
WaitForInterrupt();
status = PortF_Input();
if(status == 0x10) //sw2 press
{
SW2_Handler();
}
else if(status == 0x00) //both sw press
{
Both_Handler();
}
else if(status == 0x11) //neither sw press
{
PortF_Output(Data);
}
}
//SW2被按下 调用设置led频率的函数,使闪烁频率变慢
void SW2_Handler(void){
FallingEdges = 1;
set_LED_rate(FallingEdges);
}
//SW1 和 SW2 同时被按下 调用设置led频率的函数,使闪烁频率变得适中
void Both_Handler(void){
FallingEdges = 3;
set_LED_rate(FallingEdges);
}
重要模块6:设计串口通信,达到开发板对于不同输入信息的不同响应
//输出提示语
UART_OutString(">please input a color for LED: ");
//输入颜色,如“red”,“white”等
UART_InString(string,19);
UART_OutString("'\n>input color is ="); UART_OutString(string); OutCRLF();
//判断输入的颜色,并设置灯的颜色
if(!strcmp(string,"red"))
{
choose=1;
Data=RED;
}
else if(!strcmp(string,"blue"))
{
choose=2;
Data=BLUE;
}
else if(!strcmp(string,"green"))
{
choose=3;
Data=GREEN;
}
else if(!strcmp(string,"yellow"))
{
choose=4;
Data=YELLOW;
}
else if(!strcmp(string,"lightblue"))
{
choose=5;
Data=LBLUE;
}
else if(!strcmp(string,"purple"))
{
choose=6;
Data=PURPLE;
}
else if(!strcmp(string,"white"))
{
choose=7;
Data=WHITE;
}
实验代码
主函数代码
// PeriodicTimer0AInts.c
// Runs on LM4F120/TM4C123
// Use Timer0A in periodic mode to request interrupts at a particular
// period.
// Daniel Valvano
// September 11, 2013
/* This example accompanies the book
"Embedded Systems: Real Time Interfacing to Arm Cortex M Microcontrollers",
ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2014
Program 7.5, example 7.6
Copyright 2014 by Jonathan W. Valvano, [email protected]
You may use, edit, run or distribute this file
as long as the above copyright notice remains
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
For more information about my classes, my research, and my books, see
http://users.ece.utexas.edu/~valvano/
*/
// oscilloscope or LED connected to PF3-1 for period measurement
// When using the color wheel, the blue LED on PF2 is on for four
// consecutive interrupts then off for four consecutive interrupts.
// Blue is off for: dark, red, yellow, green
// Blue is on for: light blue, blue, purple, white
// Therefore, the frequency of the pulse measured on PF2 is 1/8 of
// the frequency of the Timer0A interrupts.
#include "inc/tm4c123gh6pm.h"
#include
#include "PLL.h"
#include "Timer0A.h"
#include "UART.h"
#define PF1 (*((volatile uint32_t *)0x40025008))
#define PF2 (*((volatile uint32_t *)0x40025010))
#define PF3 (*((volatile uint32_t *)0x40025020))
#define LEDS (*((volatile uint32_t *)0x40025038))
#define RED 0x02
#define BLUE 0x04
#define GREEN 0x08
#define YELLOW 0x0A
#define LBLUE 0x0C
#define PURPLE 0x06
#define WHITE 0x0E
#define DARK 0x00
#define WHEELSIZE 2 // must be an integer multiple of 2
// red, yellow, green, light blue, blue, purple, white, dark
//const long COLORWHEEL[WHEELSIZE] = {RED, RED+GREEN, GREEN, GREEN+BLUE, BLUE, BLUE+RED, RED+GREEN+BLUE, 0};
const long COLORWHEEL1[WHEELSIZE] = {RED, 0};
const long COLORWHEEL2[WHEELSIZE] = {BLUE, 0};
const long COLORWHEEL3[WHEELSIZE] = {GREEN, 0};
const long COLORWHEEL4[WHEELSIZE] = {YELLOW, 0};
const long COLORWHEEL5[WHEELSIZE] = {LBLUE, 0};
const long COLORWHEEL6[WHEELSIZE] = {PURPLE, 0};
const long COLORWHEEL7[WHEELSIZE] = {WHITE, 0};
void DisableInterrupts(void); // Disable interrupts
void EnableInterrupts(void); // Enable interrupts
long StartCritical (void); // previous I bit, disable interrupts
void EndCritical(long sr); // restore I bit to previous value
void WaitForInterrupt(void); // low power mode
static int choose=1;
void UserTask(void){
static int i = 0;
if(choose==1)
{
LEDS = COLORWHEEL1[i];
}
else if(choose==2)
{
LEDS = COLORWHEEL2[i];
}
else if(choose==3)
{
LEDS = COLORWHEEL3[i];
}
else if(choose==4)
{
LEDS = COLORWHEEL4[i];
}
else if(choose==5)
{
LEDS = COLORWHEEL5[i];
}
else if(choose==6)
{
LEDS = COLORWHEEL6[i];
}
else if(choose==7)
{
LEDS = COLORWHEEL7[i];
}
i = i + 1;
if(i==2)
{
i=0;
}
}
// if desired interrupt frequency is f, Timer0A_Init parameter is busfrequency/f
void OutCRLF(void){
UART_OutChar(CR);
UART_OutChar(LF);
}
#define F20KHZ (50000000/20000)
#define F16HZ (50000000/16)
#define F8HZ (50000000/8)
#define F4HZ (50000000/4)
#define F2HZ (50000000/2)
#define F1HZ (50000000)
/***********************/
#define GPIO_LOCK_KEY 0x4C4F434B // Unlocks the GPIO_CR register
#define PF0 (*((volatile uint32_t *)0x40025004))
#define PF4 (*((volatile uint32_t *)0x40025040))
#define SWITCHES (*((volatile uint32_t *)0x40025044))
#define SW1 0x10 // on the left side of the Launchpad board
#define SW2 0x01 // on the right side of the Launchpad board
#define SYSCTL_RCGC2_GPIOF 0x00000020 // port F Clock Gating Control
/***********************/
/********Edge Counter********/
volatile uint32_t FallingEdges = 3;
void EdgeCounter_Init(void){
SYSCTL_RCGCGPIO_R |= 0x00000020; // (a) activate clock for port F
FallingEdges = 3; // (b) initialize counter
GPIO_PORTF_DIR_R &= ~0x10; // (c) make PF4 in (built-in button)
GPIO_PORTF_AFSEL_R &= ~0x10; // disable alt funct on PF4
GPIO_PORTF_DEN_R |= 0x10; // enable digital I/O on PF4
GPIO_PORTF_PCTL_R &= ~0x000F0000; // configure PF4 as GPIO
GPIO_PORTF_AMSEL_R = 0; // disable analog functionality on PF
GPIO_PORTF_PUR_R |= 0x10; // enable weak pull-up on PF4
GPIO_PORTF_IS_R &= ~0x10; // (d) PF4 is edge-sensitive
GPIO_PORTF_IBE_R &= ~0x10; // PF4 is not both edges
GPIO_PORTF_IEV_R &= ~0x10; // PF4 falling edge event
GPIO_PORTF_ICR_R = 0x10; // (e) clear flag4
GPIO_PORTF_IM_R |= 0x10; // (f) arm interrupt on PF4 *** No IME bit as mentioned in Book ***
NVIC_PRI7_R = (NVIC_PRI7_R&0xFF00FFFF)|0x00A00000; // (g) priority 5
NVIC_EN0_R = 0x40000000; // (h) enable interrupt 30 in NVIC
EnableInterrupts(); // (i) Clears the I bit
}
void set_LED_rate(uint32_t rate){
switch(rate){
case 1:
Timer0A_Init(&UserTask, F1HZ);
break;
case 2:
Timer0A_Init(&UserTask, F2HZ);
break;
case 3:
Timer0A_Init(&UserTask, F4HZ);
break;
case 4:
Timer0A_Init(&UserTask, F8HZ);
break;
case 5:
Timer0A_Init(&UserTask, F16HZ);
break;
}
}
void GPIOPortF_Handler(void){ //sw1 press
GPIO_PORTF_ICR_R = 0x10;// acknowledge flag0
FallingEdges = 5;
set_LED_rate(FallingEdges);
}
void PortF_Init(void){
volatile uint32_t delay;
SYSCTL_RCGCGPIO_R |= 0x00000020; // 1) activate clock for Port F
while((SYSCTL_PRGPIO_R&0x0020) == 0){};
GPIO_PORTF_LOCK_R = 0x4C4F434B; // 2) unlock GPIO Port F
GPIO_PORTF_CR_R = 0x1F; // allow changes to PF4-0
// only PF0 needs to be unlocked, other bits can't be locked
GPIO_PORTF_AMSEL_R = 0x00; // 3) disable analog on PF
GPIO_PORTF_PCTL_R = 0x00000000; // 4) PCTL GPIO on PF4-0
GPIO_PORTF_DIR_R = 0x0E; // 5) PF4,PF0 in, PF3-1 out
GPIO_PORTF_AFSEL_R = 0x00; // 6) disable alt funct on PF7-0
GPIO_PORTF_PUR_R = 0x11; // enable pull-up on PF0 and PF4
GPIO_PORTF_DEN_R = 0x1F; // 7) enable digital I/O on PF4-0
}
uint32_t PortF_Input(void){
return (GPIO_PORTF_DATA_R&0x11); // read PF4,PF0 inputs
}
void PortF_Output(uint32_t data){ // write PF3-PF1 outputs
GPIO_PORTF_DATA_R = data;
}
void SW2_Handler(void){
FallingEdges = 1;
set_LED_rate(FallingEdges);
}
void Both_Handler(void){
FallingEdges = 3;
set_LED_rate(FallingEdges);
}
/********End Edge Counter***********/
int strcmp(const char *str1,const char *str2)
{
while(*str1 == *str2)
{
if(*str1 == '\0')
return 0;
str1++;
str2++;
}
return *str1 - *str2;
}
//debug code
int main(void){
PLL_Init(); // bus clock at 50 MHz
char ch;
char string[20];// global to assist in debugging
uint32_t n;
uint32_t Data;
UART_Init(); // initialize UART
UART_OutString(">please input a color for LED: ");
UART_InString(string,19);
UART_OutString("'\n>input color is ="); UART_OutString(string); OutCRLF();
if(!strcmp(string,"red"))
{
choose=1;
Data=RED;
}
else if(!strcmp(string,"blue"))
{
choose=2;
Data=BLUE;
}
else if(!strcmp(string,"green"))
{
choose=3;
Data=GREEN;
}
else if(!strcmp(string,"yellow"))
{
choose=4;
Data=YELLOW;
}
else if(!strcmp(string,"lightblue"))
{
choose=5;
Data=LBLUE;
}
else if(!strcmp(string,"purple"))
{
choose=6;
Data=PURPLE;
}
else if(!strcmp(string,"white"))
{
choose=7;
Data=WHITE;
}
uint32_t status;
PortF_Init();
LEDS = 0;// turn all LEDs off
Timer0A_Init(&UserTask, F1HZ);
EnableInterrupts();
EdgeCounter_Init();
while(1){
WaitForInterrupt();
status = PortF_Input();
if(status == 0x10) //sw2 press
{
SW2_Handler();
}
else if(status == 0x00) //both sw press
{
Both_Handler();
}
else if(status == 0x11) //neither sw press
{
PortF_Output(Data);
}
}
}