嵌入式arm代码改写

原题目
识别多个按键的输入情况,并控制蜂鸣器鸣叫。以K1、K2的状态表示2位二进制数(按下表示“1”,未按表示“0”,且K1对应低位)。若该二进制数中有奇数个“1”,则蜂鸣器以1秒(定时器中断实现)的间隔鸣叫,同时点亮LED1;若该二进制数中有偶数个“1”,则蜂鸣器以2秒(定时器中断实现)的间隔鸣叫,同时点亮LED1和LED2。K3按下时,蜂鸣器以1秒(定时器中断实现)的间隔鸣叫对应的次数,同时四个LED灯(LED1~LED4)以相同的频率闪烁对应的次数,之后蜂鸣器停止鸣叫,所有LED保持常亮。K4按下时,清除按键状态,所有LED熄灭,并关闭蜂鸣器,系统进入初始状态。

总体思想:利用定时器每个计数周期触发一次中断的特性来设计时间标志timer,
并设计主程序通过轮询的方式查询按键事件。
    根据对题意的理解,我们小组商议决定把题目描述归纳为4种模式,这4种模式分别以整形变量flag=1234记录。
    flag=1代表按下了奇数个“1”,设置GPKDAT = 0xef使LED1点亮。
    flag=2代表按下了偶数个“1”,设置GPKDAT = 0xcf使LED1和LED2点亮。
    flag=3代表K3按下,在delay(300000)前后分别设置GPKDAT = 0x0f,GPKDAT     = 0xff
实现题目要求的“四个LED灯(LED1~LED4)以相同的频率闪烁对应的次数,之后蜂鸣器停止鸣叫,
所有LED保持常亮。”
    flag=4代表K4按下,设置GPKDAT = 0xff,使所用LED灯熄灭,同时设置number=0b00,number_turn=0b00
,count=0清除按键状态。
    中断处理函数内设置计数器timer,主函数内定时器初始化,用flag标记此时对应的状态,再对应按键的处理中,
亮灯功能的实现依靠改变GPKDATA的值实现,闪烁判断通过timer的周期性改变GPKDATA的值实现。
    通过timer_init()设置定时器1秒或2秒,从而实现题目对蜂鸣器鸣叫的控制要求。


现题目
设计要求:
识别多个按键的输入情况,并控制蜂鸣器按不同的模式鸣叫。①以K2、K3的状态表示两位二进制数 (K2为最低位,按下表示 “1”,未按表示 “0”)。当按键按下时,对应的LED灯点亮,用于标识输入内 容。② K1按下时,若该二进制数中有奇数个 “1”,则蜂鸣器以1秒(定时器中断实现)的间隔鸣叫该二 进制数对应的次数,同时LED1和LED3以相同的频率闪烁对应的次数:若该二进制数中有偶数个 “1”,则 蜂鸣器以0.5秒(定时器中断实现)的间隔鸣叫,同时四个LED灯(LED1~LED4)按相同频率从LED1到LED4 逐一点亮(同一个时刻只有一个灯亮),并循环显示。③ K4按下时,清除按键状态,所有LED灯熄灭,并 关闭蜂鸣器,系统进入初始状态。
■ 说明:若采用查询方式判断按键是否按下,在程序中注意对按键的实时响应处理(即任意一个按键按 下后,程序能立即执行对应的功能操作)。LED灯亮1次+灭1次视为闪烁1次。蜂鸣器通过GPF14作为输出口 进行控制,输出高电平鸣叫,输出低电平关闭。未特别要求定时器中断实现的时间间隔,均可通过软件延 时实现。

希望给出更改后的代码并注释,说明更改思路
环境
硬件:Tiny6410嵌入式实验平台。
软件:PC机操作系统Fedora/CentOS+minicom+ARM-Linux 开发环境

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 GPKCON0             (*((volatile unsigned long *)0x7F008800))
#define GPKDATA                 (*((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)

void timer_init(unsigned long utimer,unsigned long uprescaler,unsigned long udivider,unsigned long utcntb,unsigned long utcmpb);
int flag = 0;            //模式
int count = 0;    //次数
int dat = 0;            //按下的键
int number = 0b00;                 //二进制数number预设为00
int number_turn = 0b00;                 //二进制数number预设为00

typedef void (isr) (void);
extern void asm_timer_irq();

void buzzer_on()    //蜂鸣器开
{    
    GPFDAT |= 1<<14;
}

void buzzer_off()    //蜂鸣器关
{
    GPFDAT &= ~(1<<14);
}

void buzzer_init(void)        //蜂鸣器初始化
{
    // set GPF14 as output
    GPFCON |= 1<<28;
    GPFCON &= ~(1<<29);
}

void delay(volatile int i)        //延时函数(volatile防止代码被优化,强制执行i次)
{
    while(i--);
}



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;
    
}

// timer0中断的中断处理函数
void do_irq()
{
    unsigned long uTmp;
    //清timer0的中断状态寄存器
    uTmp = TINT_CSTAT;
    TINT_CSTAT = uTmp;
    VIC0ADDRESS=0x0;    

      if(flag==3)
       {
           if(count>0)
               {
               buzzer_on();
               GPKDAT = 0x0f;
               delay(300000);
               buzzer_off();
               GPKDAT = 0xff;            //所有LED熄灭
               count--;
               }
           else  
              {
               GPKDAT = 0x0f;
              }
       }
     if(flag==1)
       {
           buzzer_on();
           delay(300000);
           buzzer_off();
           GPKDAT = 0xef;
       }
     if(flag==2)
       {
           buzzer_on();
           delay(300000);
           buzzer_off();
           GPKDAT = 0xcf;
       }
     if(flag==4)
       {
           flag=0; 
           GPKDAT = 0xff;            //所有LED熄灭
           buzzer_off();                   //关闭buzzer
       }
}

// 初始化timer
void timer_init(unsigned long utimer,unsigned long uprescaler,unsigned long udivider,unsigned long utcntb,unsigned long utcmpb)
{
    unsigned long temp0;

    // 定时器的输入时钟 = 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;
}


int main()
{
    buzzer_init();
    int i=0;
    while (1)
    {
        
    // 轮询的方式查询按键事件
 
          dat = GPNDAT;                    //记录按键状态

            if(!(dat & (1<<2)))                // KEY3被按下
            {
                flag=3;
                count = number;
        }
            
            if(!(dat & (1<<0)))                 // KEY1被按下,设置二进制数低位为1
                {
                number |= 0b01;
                number_turn = ((number & 0b10)>>1) | ((number & 0b01)<<1);    //形成K1K2
                }
            if(!(dat & (1<<1)))                 // KEY2被按下,设置二进制数高位为1
                {
                number |= 0b10;
                number_turn = ((number & 0b10)>>1) | ((number & 0b01)<<1);    //形成K1K2
                }

            if(flag==3)
               {
               timer_init(0,65,4,62500,0);  //定时器设置为2s
               }
            else if(number == number_turn)       //二进制数中有偶数个1 
               {
                flag=2;
                timer_init(0,65,4,62500*2,0);  //定时器设置为2s
               }
           else
              {
                flag=1;
                timer_init(0,65,4,62500,0);  //定时器设置为2s
              }
        if(!(dat & (1<<3)))                // KEY4被按下
        {
            flag=4;
                number=0b00;
                number_turn=0b00;
                count=0;
                timer_init(0,65,4,62500,0);  //定时器设置为1s
        }
    }
        
            
    return 0;
}

源于chatGPT仅供参考

以下是一个嵌入式代码实现的示例,用于识别多个按键输入情况,并控制蜂鸣器和LED的状态。请注意,这是一个基本的示例,您可能需要根据具体硬件平台和使用的编程语言进行适当的修改。

```cpp
#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 16000000UL  // 设置主频16MHz
#include <util/delay.h>

volatile uint8_t keyState = 0;  // 按键状态变量

void initialize()
{
    // 初始化IO口和定时器

    // 配置按键引脚为输入, K1-K4分别连接到PD0-PD3
    DDRD &= ~(1 << PORTD0) & ~(1 << PORTD1) & ~(1 << PORTD2) & ~(1 << PORTD3);
    // 启用上拉电阻
    PORTD |= (1 << PORTD0) | (1 << PORTD1) | (1 << PORTD2) | (1 << PORTD3);

    // 配置LED引脚为输出, LED1-LED4分别连接到PB0-PB3
    DDRB |= (1 << PORTB0) | (1 << PORTB1) | (1 << PORTB2) | (1 << PORTB3);

    // 配置蜂鸣器引脚为输出, 连接到PC0
    DDRC |= (1 << PORTC0);

    // 配置定时器0, 使用CTC模式
    TCCR0A = (1 << WGM01);
    // 设置定时器0的计数值,用于不同频率的蜂鸣器和LED闪烁
    OCR0A = 15;  // 16MHz / (2 * 256 * (15 + 1)) = 520Hz
    // 启用定时器0的比较匹配中断
    TIMSK0 |= (1 << OCIE0A);

    // 允许中断
    sei();
}

// 获取按键状态
uint8_t readKeys()
{
    // 使用位掩码读取按键状态
    uint8_t keys = PIND & 0x0F;
    return keys;
}

// 判断二进制数中1的个数是奇数还是偶数
bool isOdd(uint8_t num)
{
    int count = 0;

    while (num) {
        count += num & 1;
        num >>= 1;
    }

    return count % 2 != 0;
}

void toggleLEDs()
{
    // 根据按键状态点亮或熄灭LED
    if (keyState == 0) {
        PORTB &= ~(1 << PORTB0) & ~(1 << PORTB1) & ~(1 << PORTB2) & ~(1 << PORTB3);
    } else {
        PORTB |= (1 << PORTB0);

        if (!isOdd(keyState)) {
            PORTB |= (1 << PORTB1);
        }
    }
}

void toggleBuzzer(bool state)
{
    if (state) {
        PORTC |= (1 << PORTC0);
    } else {
        PORTC &= ~(1 << PORTC0);
    }
}

void toggleLEDsWithBuzzer(uint8_t count)
{
    for (int i = 0; i < count; i++) {
        PORTB ^= (1 << PORTB0) | (1 << PORTB1) | (1 << PORTB2) | (1 << PORTB3);
        _delay_ms(500);
    }
}

// 定时器中断处理程序
ISR(TIMER0_COMPA_vect)
{
    static uint16_t timerCount = 0;
    static bool buzzerState = false;

    timerCount++;

    // 每隔1秒或2秒更新蜂鸣器状态
    if (timerCount >= 520) {
        timerCount = 0;

        // 根据按键状态和计时器间隔设置蜂鸣器状态
        if (keyState != 0) {
            if (isOdd(keyState)) {
                toggleBuzzer(buzzerState);
                buzzerState = !buzzerState;
            } else {
                toggleBuzzer(true);


你用Tiny6410这种ARM11芯片就做几个按键和led,真够浪费资源的