CSM32RV003开发板的按键及timer1溢出中断的应用 - RISC-V MCU技术社区 - 电子技术论坛 - 广受欢迎的专业电子论坛
分享 收藏 返回

[文章]

CSM32RV003开发板的按键及timer1溢出中断的应用

按键及timer1

1、前言

申请的CSM32RV003开发板研究好长一段时间了,但是还有不少问题需要解决,一点一点的啃,终于把I/O口和timer1溢出中断弄得差不多了,这里感谢南京中科微的工程师和微信群的好友的帮助。

2、程序功能:

PA3外接按键,设置为下拉,接电源时按键触发。

开机白色LED亮2s,然后红、绿、蓝三色LED按150ms间隔循环闪烁,

由于设置了timer1中断,500ms中断触发一次,所以PA6接的黄LED按500ms规律闪烁。

当PA3按键按了一下后,红、绿、蓝三色LED按800ms间隔循环闪烁10次,然后恢复到

主程序运行状态:红、绿、蓝三色LED按100ms间隔循环闪烁。

3、代码

这里贴出了main.c代码

/*************************************************
    \\file    main.c
    \\brief   main function for test demo
    \\version V0.1, 2023-10-28, firmware for CSM32RV003
    在原厂资料改003_reset_EN.zip的基础上改写
    程序功能:    PA3外接按键,设置为下拉,接电源时按键触发。
	开机白色LED亮2s,然后红、绿、蓝三色LED按150ms间隔循环闪烁,
	由于设置了timer1中断,500ms中断触发一次,所以PA6接的黄LED按500ms规律闪烁。
	当PA3按键按了一下后,红、绿、蓝三色LED按800ms间隔循环闪烁10次,然后恢复到
	主程序运行状态:红、绿、蓝三色LED按100ms间隔循环闪烁。

********************************************************/


/*************************************************

\\file    main.c

\\brief   main function for test demo

\\version V0.1, 2023-10-28, firmware for CSM32RV003

在原厂资料改003_reset_EN.zip的基础上改写

程序功能:

PA3外接按键,设置为下拉,接电源时按键触发。

开机白色LED亮2s,然后红、绿、蓝三色LED按150ms间隔循环闪烁,

由于设置了timer1中断,500ms中断触发一次,所以PA6接的黄LED按500ms规律闪烁。

当PA3按键按了一下后,红、绿、蓝三色LED按800ms间隔循环闪烁10次,然后恢复到

主程序运行状态:红、绿、蓝三色LED按100ms间隔循环闪烁。

********************************************************/

#include "headfile.h"

#define  KEY_PA3      PIN3      //按键位置

#define  LED_B_PA8    PIN8      //蓝B_LED 位置   LED_B__PA8  LED_G__PA9 LED_R__PA12

#define  LED_G_PA9    PIN9     //绿G_LED 位置

#define  LED_R_PA12   PIN12    //红R_LED 位置

#define  LED_Y_PA6    PIN6      //黄Y_LED 位置

#define SFT                  ((SFT_TypeDef *)SFT_BASE)

#define SFT_BASE             0x30000360UL

volatile uint32_t NRST_EN;

/********************************

//根据timer.c修改  参考https://bbs.elecfans.com/jishu_2241443_1_1.html

//修改要在timer.c中进行 !!!!!!!!!!!!!!!!!!!!!!!

//该函数从timer.c中剪切来的

void Timer1_UpCounting_Mode_Init(void)      //Timer1向上计数

{

TIMER1->CR1 = 0;          //CR1[0]计数器开关:0-关闭,1-开启

TIMER_CLKEN->CLKEN  |= 1;   //CLKEN[8] Timer2时钟开关:1开启,0-关闭

//CLKEN[0] Timer1时钟开关:1开启,0-关闭


TIMER1->PSC = 32000-1;    //预分频  32MHZ/1KHZ=32000,时钟1KHZ
TIMER1->ARR = 500-1;     //自动重装寄存器       定时周期500ms
TIMER1->RCR = 0;         //重复计数
TIMER1->IER = 1 << 0;        //使能TIMER1中断:1-使能,0-关闭


}

*******************************************************************/

//有了如下的函数所以可以把中断函数的在此处修改

void Timer1_Update_IRQhandler(void)   **attribute** ((interrupt("SiFive-CLIC-preemptible")));   //该函数在it.h中

void Timer1_Update_IRQhandler(void)           //原函数在原厂的it.c中,要把it.c中的该函数注释掉

{

Timer1_Update_Isr();

}

void Timer1_Update_Isr(void)               //更新  //该函数在原厂的timer.c中,要把它注释掉

{

if(TIMER1->SR&0x1)

{

TIMER1->SR &= ~0x1;                 //原厂的

//TIMER1->SR &= ~(0x1 << 0);        //一样的

GPIO_Toggle(GPIOA,LED_Y_PA6  );      //黄灯闪烁,间隔500ms

}

}

int main(void)

{


typedef struct
{
    volatile uint32_t EN;
    volatile uint32_t NRST_EN;
}SFT_TypeDef;

SFT->NRST_EN=0;   //使能MCU003PA15硬件复位@


///---- 系统总中断控制 -------------------------------------------------------------------------------------------------
//SYS_Interrupt_Enable();//CLIC开总中断
//SYS_Interrupt_Disable();//CLIC关总中断

//ee_printf("\\nHello CSM32RV20:");
//printf("Hello CSM32RV20:\\r\\n");


///----Chapter 5 GPIO Test Init ---------------------------------------------------------------------------------
//输出端口的设置
GPIO_MODE_Init(GPIOA,LED_B_PA8,GPIO_MODE_OUTPUT);  //GPIO的PA8输出模式
GPIO_MODE_Init(GPIOA,LED_G_PA9 ,GPIO_MODE_OUTPUT);    //端口初始化,PA9输出模式
GPIO_MODE_Init(GPIOA,LED_R_PA12,GPIO_MODE_OUTPUT);  //GPIO的PA12输出模式
GPIO_MODE_Init(GPIOA,LED_Y_PA6,GPIO_MODE_OUTPUT);  //GPIO的PA6输出模式

 //为了驱动不同的负载,可以设置不同的输出方式
//GPIO_OutType_Init(GPIOA,PIN12,GPIO_OTYPE_ODOS_ON );        //PA12推免输出
//GPIO_OutType_Init(GPIOA,PIN12,GPIO_OTYPE_ODOS_OFF  );      //PA12 关闭开漏、开源功能
//GPIO_OutType_Init(GPIOA,PIN12,GPIO_OTYPE_OS_ON  );         //PA12开源输出
//GPIO_OutType_Init(GPIOA,PIN12, GPIO_OTYPE_ODOS_OFF);       //PA12关闭开漏、开源功能
//GPIO_OutType_Init(GPIOB,PIN10, GPIO_OTYPE_ODOS_OFF);       //PB10关闭开漏、开源功能


/***************************************************************/


//点亮开发板上的三基色2s
GPIO_Write(GPIOA, LED_G_PA9,GPIO_RESET);              //GPIO的PA9输出0
//GPIO_Write(GPIOA,PIN9, SET);                  //GPIO的PA9输出1
GPIO_Write(GPIOA, LED_B_PA8   ,GPIO_RESET);             //GPIO的PA8 输出0
GPIO_Write(GPIOA, LED_R_PA12,GPIO_RESET);            //GPIO的PA12 输出0
Delay32M_ms(2000);                            //调用32MHZ系统的延时函数 延时2s

//熄灭开发板上的三基色
GPIO_Write(GPIOA, LED_B_PA8 ,GPIO_SET);   //PA8输出1  PA8接Blue LED 低电平LED亮  关闭
GPIO_Write(GPIOA,LED_G_PA9,1);   //PA9输出1    PA9接Green LED  低电平LED亮  关闭
GPIO_Write(GPIOA,LED_R_PA12,1);   //PA12输出   PA9接RED LED  低电平LED亮  关闭


//输入口的设置

GPIO_InType_Init( GPIOA,  KEY_PA3,GPIO_MODE_INPUT);  //GPIO的PA3输入模式,外接按键

//GPIO_PULL_Init(GPIOA,  KEY_PA3, GPIO_PULLUP);      //PA3 上拉    未按下时是1

GPIO_PULL_Init(GPIOA,  KEY_PA3, GPIO_PULLDOWN);      // PA3下拉    未按下时是0

//GPIO_PULL_Init(GPIOA,  KEY_PA3,  0GPIO_NOPULL );   // PA3浮空


//这里中断设置放LED及按键的后边,开机三个LED同时发光2s,然后中断动作
///---------- System Init ----------///
CLIC_Init();//系统中断配置
//SysClock_RC_Mode_Init();          //系统时钟初始化:RC模式
 //SysClock_Crystal_Mode_Init();     //系统时钟初始化:晶振模式
//SysClock_PLL_Mode_Init();          //系统时钟初始化:PLL模式
 SysClock_Test_Init();              //系统时钟初始化

Timer1_UpCounting_Mode_Init( );                         //Timer1向上计数,有修改
Interrupt_Level(TIMER1_updata_int_ID,INT_LEVEL0);       //CLIC设置中断抢占级别  优先级 lic.h中
Interrupt_Enable(TIMER1_updata_int_ID);                //CLIC使能中断  允许Timer1溢出中断

//使能系统总中断
 SYS_Interrupt_Enable( );                              //CLIC开总中断

while(1)
{

//if( !GPIO_Read(GPIOA, PIN3)  )     //GPIO输入上拉时 读输入为0表示按键按下
 if( GPIO_Read(GPIOA, KEY_PA3)  )     //GPIO输入下拉时 读输入为1表示按键按下
 {
      //自己加的代码
      Delay32M_ms(20);                  //20ms消除抖动
      while(GPIO_Read(GPIOA, KEY_PA3)) ;   //等待按键抬起
       while(!GPIO_Read(GPIOA, KEY_PA3)) ;   //等待按键抬起
     for(uint8_t i=0;i<10;i++)            //3个LED依次闪烁10次
     {
        GPIO_Toggle(GPIOA,LED_R_PA12);       //PA12翻转 开发板上PA12接Red LED
        Delay32M_ms(800);
        GPIO_Write(GPIOA,LED_R_PA12,GPIO_SET);      //关闭红灯,消除余辉影响

        GPIO_Toggle(GPIOA,LED_G_PA9);         //PA9翻转 开发板上PA9接Green LED
        Delay32M_ms(800);
        GPIO_Write(GPIOA,LED_G_PA9,GPIO_SET);    //PA9输出1 关闭绿灯 消除余辉影响

        GPIO_Toggle(GPIOA,LED_B_PA8);      //GPIO 翻转 开发板上PA8接Blue LED
        Delay32M_ms(800);
        GPIO_Write(GPIOA,LED_B_PA8,1);     //PA8输出1 关闭蓝灯消除余辉影响
     }
 }
     else        //无按键按下,红、绿、蓝三色LED按间隔150ms闪烁
     {
        GPIO_Toggle(GPIOA,LED_R_PA12);       //PA12翻转 开发板上PA12接Red LED
        Delay32M_ms(100);
        GPIO_Write(GPIOA,LED_R_PA12,GPIO_SET);      //关闭红灯,消除余辉影响

        GPIO_Toggle(GPIOA,LED_G_PA9);         //PA9翻转 开发板上PA9接Green LED
        Delay32M_ms(100);
        GPIO_Write(GPIOA,LED_G_PA9,GPIO_SET);    //PA9输出1 关闭绿灯 消除余辉影响

        GPIO_Toggle(GPIOA,LED_B_PA8);      //GPIO 翻转 开发板上PA8接Blue LED
        Delay32M_ms(100);
        GPIO_Write(GPIOA,LED_B_PA8,1);      //PA8输出1 关闭蓝灯消除余辉影响
  }

}
return 0;


}
  1. 经验

(1)关于原厂无参库函数(非中断函数)的修改

一定要在原函数所在的*.c文件中修改,函数头不可改动,大括号里的内容可以改动,为了与原厂内容有所区分,最好把原厂内容注释掉。当然为了便于看,可以把修改后的函数复制粘贴到main.c中再注释掉。如本例的void Timer1_UpCounting_Mode_Init(void) //Timer1向上计数

函数,大家可以查看main.ctimer.c文件。

有参函数的内容一般不需改动,我们在调用时只需修改参数即可。

(2)中断函数的修改

由于中断函数的内容一般要用户填写,所以要修改,该开源开发板又不同于普通的8位单片机,他的操作有类似于原厂无参库函数(非中断函数)的修改,修改方法以timer1为例。要在main.c中插入如下代码:

//有了如下的函数所以可以把中断函数的在此处修改
void Timer1_Update_IRQhandler(void)  __attribute__((interrupt("SiFive-CLIC-preemptible")));   //该函数在it.h中
 void Timer1_Update_IRQhandler(void)           //原函数在原厂的it.c中,要把it.c中的该函数注释掉
{
     Timer1_Update_Isr();
}

void Timer1_Update_Isr(void)               //更新  //该函数在原厂的timer.c中,要把它注释掉
{
	if(TIMER1->SR&0x1)
    {
         TIMER1->SR &= ~0x1;                 //原厂的
         //TIMER1->SR &= ~(0x1 << 0);        //一样的
        GPIO_Toggle(GPIOA,LED_Y_PA6  );      //黄灯闪烁,间隔500ms
    }

}

后面的2个函数要在相应的*.c文件中注释掉。

(3)关于ISP下载

ISP下载提示复位时,最好一直按住复位键直到下载结束。若果ISP下载失败,可以在编译软件的maicn.c窗口,cjlink一端连电脑,另一端亮开发板,点击菜单烧录/下载,用cjlink也可以,成功后再用ISP下载。

5、问题

void Timer1_Update_IRQhandler(void) **attribute** ((interrupt("SiFive-CLIC-preemptible"))); //该函数看不懂,它在it.h中的作用,以及it.h和it.c文件都起什么作用,希望有大侠可以解释一下。

更多回帖

×
发帖