返回列表 发新帖

SAM4E-EK开发板代码解读01——LED闪烁

[复制链接]

28

主题

45

帖子

1万

积分

允许发帖

积分
10186
发表于 2020-4-30 17:43:19 | 显示全部楼层 | 阅读模式
本帖最后由 Mcuzone_TKN 于 2020-5-15 09:06 编辑

关键词:Microchip Atmel  SAM4E SAM4E-EK  SAM4E16E 芯片 LED闪烁 按键

概述:解读通过GPIO控制LED的工作流程,并提供GPIO引脚修改方法。

从原理图可知(图1),LED通过GPIO进行控制,当GPIO引脚为高电平时,LED两端均为高电平,LED不亮;当GPIO引脚为低电平时,LED点亮。

LED的亮灭控制通过按键来实现,当按键按下时,LED灭,按键再次按下,LED亮。

按键采用中断方式,初始化流程为:
分配时钟给指定按键引脚->引脚配置为输入模式->设定下降沿出发->使能中断。


LED的初始化流程为:
分配时钟给指定按键引脚->引脚配置为输出模式->初始化输出为高,此时LED不亮


打开产品光盘SAM4E16E-EK/SAM4E16E-EK中文资料/softpack软件包/Atmel Studio 7,打开01_GETTING-STARTED例子。

//当对应的按钮按下时,就改变LED的状态
//修改LED 可以选择对应的LED闪烁
static void ProcessButtonEvt (uint8_t uc_button)
{

        if (uc_button == 0) {
                g_b_led0_active = !g_b_led0_active;

               //如果LED0激活就用LED0
                if (!g_b_led0_active) {
                        ioport_set_pin_level(LED0_GPIO, IOPORT_PIN_LEVEL_HIGH);
                }
        }

#ifdef LED1_GPIO   
        else {
                g_b_led1_active = !g_b_led1_active;

                // 如果LED1激活的就用LED1
                if (g_b_led1_active) {
                        ioport_set_pin_level(LED1_GPIO, IOPORT_PIN_LEVEL_LOW);
                        tc_start(TC0, 0);
                }
               
//否则就关闭LED1

                else {
                        ioport_set_pin_level(LED1_GPIO, IOPORT_PIN_LEVEL_HIGH);
                        tc_stop(TC0, 0);
                }
        }
#endif
}


//处理按键1上升边中断   处理LED1的变化
static void Button1_Handler(uint32_t id, uint32_t mask)
{
        if (PIN_PUSHBUTTON_1_ID == id && PIN_PUSHBUTTON_1_MASK == mask) {
                ProcessButtonEvt(0);
        }
}

#ifndef BOARD_NO_PUSHBUTTON_2
//处理按钮2下降沿中断     处理LED2的变化
static void Button1_Handler (uint32_t id, uint32_t mask)
{
        if (PIN_PUSHBUTTON_2_ID == id && PIN_PUSHBUTTON_2_MASK == mask) {
                ProcessButtonEvt(1);
        }
}
#endif


//配置按钮 将PIO配置为输入 并生成相应的中断 按下或者释放

static void configure_buttons (void)  
{
        //配置按钮1
        pmc_enable_periph_clk(PIN_PUSHBUTTON_1_ID);
        pio_set_debounce_filter(PIN_PUSHBUTTON_1_PIO, PIN_PUSHBUTTON_1_MASK, 10);
        
//上升沿中断

        pio_handler_set(PIN_PUSHBUTTON_1_PIO, PIN_PUSHBUTTON_1_ID,
                        PIN_PUSHBUTTON_1_MASK, PIN_PUSHBUTTON_1_ATTR, Button1_Handler);
        NVIC_EnableIRQ((IRQn_Type) PIN_PUSHBUTTON_1_ID);
        pio_handler_set_priority(PIN_PUSHBUTTON_1_PIO,
                        (IRQn_Type) PIN_PUSHBUTTON_1_ID, IRQ_PRIOR_PIO);
        pio_enable_interrupt(PIN_PUSHBUTTON_1_PIO, PIN_PUSHBUTTON_1_MASK);

        #ifndef BOARD_NO_PUSHBUTTON_2
      
//配置按钮2

        pmc_enable_periph_clk(PIN_PUSHBUTTON_2_ID);
        pio_set_debounce_filter(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_MASK, 10);
        
//下降沿中断

        pio_handler_set(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_ID,
                        PIN_PUSHBUTTON_2_MASK, PIN_PUSHBUTTON_2_ATTR, Button2_Handler);
        NVIC_EnableIRQ((IRQn_Type) PIN_PUSHBUTTON_2_ID);
        pio_handler_set_priority(PIN_PUSHBUTTON_2_PIO,
                        (IRQn_Type) PIN_PUSHBUTTON_2_ID, IRQ_PRIOR_PIO);
        pio_enable_interrupt(PIN_PUSHBUTTON_2_PIO, PIN_PUSHBUTTON_2_MASK);
#endif
}

//用于TC0中断的中断处理程序,切换LED的状态  

void TC0_Handler (void)   

{
        volatile uint32_t ul_dummy;

        //清除状态位以确定中断
        ul_dummy = tc_get_status(TC0, 0);

        //避免编译器报警
        UNUSED(ul_dummy);

#ifdef LED1_GPIO
        //切换LED状态
        ioport_toggle_pin_level(LED1_GPIO);
#endif

        printf("2 ");
}



//配置定时器计数器0 每250ms产生一个中断
static void configure_tc(void)  

{
        uint32_t ul_div;
        uint32_t ul_tcclks;
        uint32_t ul_sysclk = sysclk_get_cpu_hz();

        //配置PMC
        
pmc_enble_periph_clk(ID_TC0);  


        //将TC配置成4HZ频率,在RC上比较触发器
        tc_find_mck_divisor(4, ul_sysclk, &ul_div, &ul_tcclks, ul_sysclk);
        tc_init(TC0, 0, ul_tcclks | TC_CMR_CPCTRG);
        tc_write_rc(TC0, 0, (ul_sysclk / ul_div) / 4);

        
//配置RC并且启用中断

        NVIC_EnableIRQ((IRQn_Type) ID_TC0);
        tc_enable_interrupt(TC0, 0, TC_IER_CPCS);

#ifdef LED1_GPIO
        
//如果启用LED1就启用计数器

        if (g_b_led1_active) {
                tc_start(TC0, 0);  
        }
#else
        tc_start(TC0, 0);
#endif
}


int main(void)
{      
       //初始化SAM系统
        sysclk_init();
        board_init();   

       //初始化uart
        configure_console();


       //输出例子信息
        puts(STRING_HEADER);

      
//配置系统时钟为1ms    修改1000可以改变LED闪烁时间   

        puts("Configure system tick to get 1ms tick period.\r");
        if (SysTick_Config(sysclk_get_cpu_hz() / 1000)) {
                puts("-F- Systick configuration error\r");
                while (1);
        }

        puts("Configure TC.\r");
        configure_tc();

        puts("Configure buttons with debouncing.\r");
        configure_buttons();

        printf("Press %s to Start/Stop the %s blinking.\r\n",
                        PUSHBUTTON_1_NAME, LED_0_NAME); // k3按下 LED0熄灭    按键再次按下 LED0亮

#ifndef BOARD_NO_PUSHBUTTON_2
        printf("Press %s to Start/Stop the %s blinking.\r\n",
                        PUSHBUTTON_2_NAME, LED_1_NAME); //k4按下 LED1熄灭   按键再次按下 LED1亮
#endif

        while (1) {
               //等待LED激活
               
while (!g_b_led0_active);

               //如果激活 就切换LED的状态
                if (g_b_led0_active) {
                        ioport_toggle_pin_level(LED0_GPIO);
                        printf("1 ");
                }
               //等待500ms
                mdelay(500);
        }
}




原理图

原理图
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表