合工大嵌入式系统课程设计
设计要求:
根据单个按键输入情况控制LED灯的不同显示效果。K1连续按下偶数次时,四个LED灯(LED1~LED4)按1秒(定时器中断实现)的间隔同时闪烁对应的次数,然后保持LED1和LED2常亮,LED3和LED4熄灭;K1连续按下奇数次时,四个灯按0.5秒(定时器中断实现)的间隔同时闪烁对应的次数,然后保持LED1和LED2熄灭,LED3和LED4常亮。K2按下时,四个灯按1秒(定时器中断实现)的间隔逐一点亮(同一个时刻只有个灯亮),并循环显示。K3按下时,四个灯按0.5秒(定时器中断实现)的间隔逐一点亮(同一个时刻只有一个灯亮),并循环显示。K4按下时,所有灯熄灭,系统进入初始状态。
说明:程序需要区分连续按键与间隔时间按键。连续按键的间隔时间自行确定,合理即可示。
主要代码如下:
main.c
main.c:
#include "stdio.h"
#define GPKCON0 (*(volatile unsigned long *)0x7F008800)
#define GPKDAT (*(volatile unsigned long *)0x7F008808)
#define GPNCON (*(volatile unsigned long *)0x7F008830)
#define GPNDAT (*(volatile unsigned long *)0x7F008834)
#define GPFCON (*(volatile unsigned int *)0x7F0080A0)
#define GPFDAT (*(volatile unsigned int *)0x7F0080A4)
int COUNT;
void timer_init(unsigned long utimer, unsigned long uprescaler, unsigned long udivider, unsigned long utcntb, unsigned long utcmpb, int mode_x, int countk1_x);
void delay_short(volatile unsigned int n) {
while (n--) {
}
}
void delay(volatile unsigned int n) {
while (n--) {
delay_short(0x7ff);
}
}
void buzzer_init(void)
{
// set GPF14 as output
GPFCON |= 1 << 28;
GPFCON &= ~(1 << 29);
}
int main()
{
int dat = 0;
// 配置GPK4-7为输出功能
GPKCON0 = 0x11110000;
// 所有LED熄灭
GPKDAT = 0x000000f0;
// 配置GPN为输入功能
GPNCON = 0;
// 初始化buzzer
buzzer_init();
// 轮询的方式查询按键事件
while (1)
{
dat = GPNDAT;
if (dat & (1 << 0));
else {
// KEY1被按下
// 设置定时器
int countk1 = 0;
int num = 1500000;
while (num > 0)
{
//GPNDAT,低四位有效,哪位按下哪位为0
if (!(GPNDAT & (1 << 0))) //意思就是 若k1按下了 那么就进入if
{
delay(10);
countk1++; //按下一次 计数一次
num = 1500000; //把倒计时还原
while (!(GPNDAT & (1 << 0))) { ; }
}
num--;
}//while(num > 0)
COUNT = countk1;
if (countk1 % 2 == 1)
timer_init(0, 65, 4, 31250, 0, 0, countk1);
else if (countk1 % 2 == 0)
timer_init(0, 65, 4, 62500, 0, 0, countk1);
//if(GPNDAT & (1<<0))
//{
// dat = 0xfd;
//}
}
if (dat & (1 << 1));
else {
// KEY2被按下
// 设置定时器
while (!(GPNDAT & (1 << 0))) { ; }
int big = 0x6000000;
while (big > 0)
big--;
timer_init(0, 65, 4, 62500, 0, 1, 0);
}
if (dat & (1 << 2));
else
// KEY3被按下
// 设置定时器
{
while (!(GPNDAT & (1 << 0))) { ; }
timer_init(0, 65, 4, 31250, 0, 2, 0);
}
if (dat & (1 << 3));
else
// KEY4被按下
// 设置定时器
{
while (!(GPNDAT & (1 << 0))) { ; }
int big = 0x6000000;
while (big > 0)
big--;
timer_init(0, 65, 4, 31250, 0, 3, 0);
}
}
}
timer.c:
#include "stdio.h"
#define GPKCON0 (*((volatile unsigned long *)0x7F008800))
#define GPKDATA (*((volatile unsigned long *)0x7F008808))
#define GPKDAT (*((volatile unsigned long *)0x7F008808))
#define EINT0CON0 (*((volatile unsigned long *)0x7F008900))
#define EINT0MASK (*((volatile unsigned long *)0x7F008920))
#define EINT0PEND (*((volatile unsigned long *)0x7F008924))
#define PRIORITY (*((volatile unsigned long *)0x7F008280))
#define SERVICE (*((volatile unsigned long *)0x7F008284))
#define SERVICEPEND (*((volatile unsigned long *)0x7F008288))
#define VIC0IRQSTATUS (*((volatile unsigned long *)0x71200000))
#define VIC0FIQSTATUS (*((volatile unsigned long *)0x71200004))
#define VIC0RAWINTR (*((volatile unsigned long *)0x71200008))
#define VIC0INTSELECT (*((volatile unsigned long *)0x7120000c))
#define VIC0INTENABLE (*((volatile unsigned long *)0x71200010))
#define VIC0INTENCLEAR (*((volatile unsigned long *)0x71200014))
#define VIC0PROTECTION (*((volatile unsigned long *)0x71200020))
#define VIC0SWPRIORITYMASK (*((volatile unsigned long *)0x71200024))
#define VIC0PRIORITYDAISY (*((volatile unsigned long *)0x71200028))
#define VIC0ADDRESS (*((volatile unsigned long *)0x71200f00))
#define PWMTIMER_BASE (0x7F006000)
#define TCFG0 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x00)) )
#define TCFG1 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x04)) )
#define TCON ( *((volatile unsigned long *)(PWMTIMER_BASE+0x08)) )
#define TCNTB0 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x0C)) )
#define TCMPB0 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x10)) )
#define TCNTO0 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x14)) )
#define TCNTB1 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x18)) )
#define TCMPB1 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x1C)) )
#define TCNTO1 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x20)) )
#define TCNTB2 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x24)) )
#define TCMPB2 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x28)) )
#define TCNTO2 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x2C)) )
#define TCNTB3 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x30)) )
#define TCMPB3 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x34)) )
#define TCNTO3 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x38)) )
#define TCNTB4 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x3C)) )
#define TCNTO4 ( *((volatile unsigned long *)(PWMTIMER_BASE+0x40)) )
#define TINT_CSTAT ( *((volatile unsigned long *)(PWMTIMER_BASE+0x44)) )
#define GPFCON (*(volatile unsigned int *)0x7F0080A0)
#define GPFDAT (*(volatile unsigned int *)0x7F0080A4)
typedef void (isr)(void);
extern void asm_timer_irq();
extern int COUNT;
int mode;
int count;
int countk1;
void irq_init(void)
{
/* 在中断控制器里使能timer0中断 */
VIC0INTENABLE |= (1 << 23);
VIC0INTSELECT = 0;
isr** isr_array = (isr**)(0x7120015C);
isr_array[0] = (isr*)asm_timer_irq;
/*将GPK4-GPK7配置为输出口*/
GPKCON0 = 0x11110000;
//熄灭四个LED灯
GPKDATA = 0xff;
// set GPF14 as output
GPFCON |= 1 << 28;
GPFCON &= ~(1 << 29);
}
// timer0中断的中断处理函数
void do_irq()
{
// K1对应的操作
if (mode == 0)
{
if (countk1 <= 0)
{
if (COUNT % 2 == 0)
GPKDATA = 0xc0;
else
GPKDATA = 0x30;
//GPKDATA=0xff;
}
else
{
int label = count % 2;
switch (label)
{
case 0:
// 四个LED灯全部熄灭
GPKDATA = 0xff;
break;
case 1:
// 四个LED灯全部亮起
GPKDATA = 0x0;
countk1 = countk1 - 1;
break;
default:break;
}
count++;
}
}
// K2对应的操作
if (mode == 1)
{
int label = count % 4;
switch (label)
{
case 0:
// LED1 亮起,LED2、LED3、LED4熄灭
GPKDATA = 0xff;
GPKDAT &= ~(1 << 4);
break;
case 1:
// LED2 亮起,LED1、LED3、LED4熄灭
GPKDATA = 0xff;
GPKDAT &= ~(1 << 5);
break;
case 2:
// LED3 亮起,LED1、LED2、LED4熄灭
GPKDATA = 0xff;
GPKDAT &= ~(1 << 6);
break;
case 3:
// LED4 亮起,LED1、LED2、LED3熄灭
GPKDATA = 0xff;
GPKDAT &= ~(1 << 7);
break;
default:break;
}
// count加一
count++;
}
// K3对应的操作
if (mode == 2)
{
int label = count % 4;
switch (label)
{
case 0:
// LED1 亮起,LED2、LED3、LED4熄灭
GPKDATA = 0xff;
GPKDAT &= ~(1 << 4);
break;
case 1:
// LED2 亮起,LED1、LED3、LED4熄灭
GPKDATA = 0xff;
GPKDAT &= ~(1 << 5);
break;
case 2:
// LED3 亮起,LED1、LED2、LED4熄灭
GPKDATA = 0xff;
GPKDAT &= ~(1 << 6);
break;
case 3:
// LED4 亮起,LED1、LED2、LED3熄灭
GPKDATA = 0xff;
GPKDAT &= ~(1 << 7);
break;
default:break;
}
// count加一
count++;
}
// K4对应的操作
if (mode == 3)
{
GPKDATA = 0xff;
}
unsigned long uTmp;
//清timer0的中断状态寄存器
uTmp = TINT_CSTAT;
TINT_CSTAT = uTmp;
VIC0ADDRESS = 0x0;
}
// 初始化timer
void timer_init(unsigned long utimer, unsigned long uprescaler, unsigned long udivider, unsigned long utcntb, unsigned long utcmpb, int mode_x, int countk1_x)
{
unsigned long temp0;
// 设置mode值,用于判断执行哪一种操作
mode = mode_x;
countk1 = countk1_x;
// 定时器的输入时钟 = PCLK / ( {prescaler value + 1} ) / {divider value} = PCLK/(65+1)/16=62500hz
//设置预分频系数为66
temp0 = TCFG0;
temp0 = (temp0 & (~(0xff00ff))) | (uprescaler << 0);
TCFG0 = temp0;
// 16分频
temp0 = TCFG1;
temp0 = (temp0 & (~(0xf << 4 * utimer)) & (~(1 << 20))) | (udivider << 4 * utimer);
TCFG1 = temp0;
// 1s = 62500hz
TCNTB0 = utcntb;
TCMPB0 = utcmpb;
// 手动更新
TCON |= 1 << 1;
// 清手动更新位
TCON &= ~(1 << 1);
// 自动加载和启动timer0
TCON |= (1 << 0) | (1 << 3);
// 使能timer0中断
temp0 = TINT_CSTAT;
temp0 = (temp0 & (~(1 << utimer))) | (1 << (utimer));
TINT_CSTAT = temp0;
}
结果: