本帖最后由 zhjb1 于 2024-12-19 11:04 编辑
八、学习中断的应用 这个实验也不复杂,我所有的实验非必须都是基于测评三、的GPIO_LCD增加内容完成。 打开PINS_LED工程,打开main.c;此时已经有了key的中断,现在的程序计数器是采用循环语句中增加完成的: if(js>999999)js=0;else js++; 就是说while循环一次js(设定的程序计数器值)增加一个,目的是为了看程序能运行多少次宕机,当然也可以观察运行了多少个循环。在某些应用中是有意义的,但有一个致命的问题:有些代码与运行有关,时快时慢造成循环的计数值乘以时间不等于实际运行时间,这是采用系统自动中断技术是最好的方法,本实验就是为了完成此目标,很小一小步。 打开key的中断相关函数: void KEY_IRQHandler(void){ //Get interrupt flag——中断标志 if((PINS_ReadPmInt**(PMC) & (1<<KEY1_PIN)) != 0){ LED_On(LED_RED); //Clear interrupt flag——清除中断标志 PINS_ClrPinInt**Cmd(PMC, KEY1_PIN);kk=101; }else if((PINS_ReadPmInt**(PMC) & (1<<KEY2_PIN)) != 0){ LED_Off(LED_RED); //Clear interrupt flag——清除中断标志 PINS_ClrPinInt**Cmd(PMC, KEY2_PIN);kk=202; }else{ //Clear interrupt flags for all pins in the port PINS_ClrPmInt**Cmd(PMC); } } 这里只是中断执行结果,下边看main中的中断控制函数,有两个: //set PMC interrupt callback function INT_SYS_InstallHandler(PMC_IRQn,&KEY_IRQHandler,(ISR_T*) 0); 和 //Enable PMC interrupt INT_SYS_EnableIRQ(PMC_IRQn); 前一个是中断句柄——标注为回访函数,叫什么无所谓,知道是中断号和中断句柄声明; 后一句是中断向量允许。到此已经完成了一半。我们的目的是将程序计数器放在StsTick的中断函数中,因此也需要启动SysTick的这两个句柄增加如下两句(当然需要在项目中遍历搜寻此函数句柄的) 第一步: 对应第一句: INT_SYS_InstallHandler(SysTick_IRQn,&SysTick_Handler,(ISR_T*) 0); 对应第二句: INT_SYS_EnableIRQ(SysTick_IRQn); 加载key中断的附近,其实无所谓的啦,只要是系统首先的语句之后即可。 第二步:将uint32_t js;增加到g32a1xxx_int.c的前边; extern uint32_t js; 第三步:找到void SysTick_Handler(void)函数,在里面添加: js++; 之后更改原while中的if(js>999999)js=0;else js++;为: if(js>999999)js=0; 去掉js++; 至此重新编译下载后计数器的值也在快速增加,并且不会随主函数延时设定的长短改变,尽管while中有定时语句,定时100mS一循环。 主函数的代码: //main.c Main program V1.0.0 2024-03-20 Copyright (C) 2024 Geehy Semiconductor //Includes #include "user_config.h" #include "board.h" #include <stdio.h> #include <stdbool.h> #include "g32a1xxx_int.h" #include "g32a1xxx_adc.h" #include "g32a1xxx_pins.h" //#include "osif.h" #include "12864.h" //G32A1465_Examples //ADC_SoftwareConversion_Macros Macros #define ADC_INSTANCE (0U) static __IO uint32_t g_timingDelay; float g_adcMaxValue = 4096; float g_adcDifference = 3.3f; int k=0,kk=0; uint32_t js=0; float adcValue; //PINS_Led_Macros Macros #define LED_GPIO GPIOD #define BLUE_LED_PIN (0U) #define RED_LED_PIN (15U) #define GREEN_LED_PIN (16U) #define WHITE_LED_PIN (~0x00018001)//NOTE:For testing reference only! // Start SysTick void SysTick_Init(void){ //Update System Core Clock info SystemCoreClockUpdate(); //SystemFrequency/1000=1ms if(SysTick_Config(SystemCoreClock / 1000)) {while(1);}//Capture error } //Time in milliseconds Decrements the TimingDelay void SysTick_Delay_ms(__IO uint32_t nTime){g_timingDelay = nTime;while (g_timingDelay != 0);} void TimingDelay_Decrement(void){if (g_timingDelay != 0){g_timingDelay--;}} //Key IniteruptHandler void KEY_IRQHandler(void){ //Get interrupt flag if((PINS_ReadPmInt**(PMC) & (1<<KEY1_PIN)) != 0){ LED_On(LED_RED); //Clear interrupt flag PINS_ClrPinInt**Cmd(PMC, KEY1_PIN);kk=101; }else if((PINS_ReadPmInt**(PMC) & (1<<KEY2_PIN)) != 0){ LED_Off(LED_RED); //Clear interrupt flag PINS_ClrPinInt**Cmd(PMC, KEY2_PIN);kk=202; }else{ //Clear interrupt flags for all pins in the port PINS_ClrPmInt**Cmd(PMC); } } //ADC software conversion initialization configuration void ADC_init(void){ ADC_CONV_CFG_T tempAdcConvCfg0; ADC_AVG_CFG_T tempAdcAverCfg0; ADC_CALIBRATION_T tempAdcCalibration0; //Reset adc module ADC_Reset(ADC_INSTANCE); //Call default configuration ADC_ConfigConverterStruct(&tempAdcConvCfg0); tempAdcConvCfg0.clockDivision = ADC_CLK_DIVISION_4; tempAdcConvCfg0.resolution = ADC_RESOLUTION_RATIO_12BIT; //Call default configuration ADC_ConfigHwAverageStruct(&tempAdcAverCfg0); tempAdcAverCfg0.hwAvgEnable = true; tempAdcAverCfg0.hwAverage = ADC_HW_AVERAGE_32; //Call default configuration ADC_ConfigUserCalibrationStruct(&tempAdcCalibration0); tempAdcCalibration0.userGain = ADC_DEFAULT_SAMPLE_TIME; tempAdcCalibration0.userOffset = 20000u; //Set software pre triggering ADC_SetSwPretrigger(ADC_INSTANCE,ADC_SW_PRE_TRIGGER_0); //Initialize ADC based on configuration values ADC_ConfigConverter(ADC_INSTANCE,&tempAdcConvCfg0); //Initialize ADC hardware averaging function based on configuration values ADC_ConfigHwAverage(ADC_INSTANCE,&tempAdcAverCfg0); //Enable calibration function ADC_ConfigUserCalibration(ADC_INSTANCE,&tempAdcCalibration0); //Verify ADC ADC_AutoCalibration(ADC_INSTANCE); } //Read ADC value float ADC_readValue(void){ uint16_t partAdcValue; ADC_CHAN_CONFIG_T tempAdcChanCfg0; //Call default configuration ADC_ConfigChanStruct(&tempAdcChanCfg0); tempAdcChanCfg0.interruptEnable = false; tempAdcChanCfg0.channel = ADC_INPUT_CHANNEL_EXT12; //Trigger using software ADC_ConfigChan(ADC_INSTANCE, 0u, &tempAdcChanCfg0); //waiting for conversion to complete ADC_WaitConvDone(ADC_INSTANCE); //Obtain conversion results ADC_ReadChanResult(ADC_INSTANCE, 0u, &partAdcValue); return (float)partAdcValue; } void PINS_Led_Init(){ //Enable Clock to Port D CLOCK_SYS_ConfigModuleClock(PMD_CLK, NULL); //Set pin mode PINS_SetMuxModeSel(LED_RED_PORT_BASE, LED_RED_PIN, PM_MUX_AS_GPIO); PINS_SetMuxModeSel(LED_GREEN_PORT_BASE, LED_GREEN_PIN, PM_MUX_AS_GPIO); PINS_SetMuxModeSel(LED_BLUE_PORT_BASE, LED_BLUE_PIN, PM_MUX_AS_GPIO); //Set pin interrupt PINS_SetPinIntSel(LED_RED_PORT_BASE, LED_RED_PIN, PM_DMA_INT_DISABLED); PINS_SetPinIntSel(LED_GREEN_PORT_BASE, LED_GREEN_PIN, PM_DMA_INT_DISABLED); PINS_SetPinIntSel(LED_BLUE_PORT_BASE, LED_BLUE_PIN, PM_DMA_INT_DISABLED); //GPIO Initialization PINS_SetPins(LED_RED_GPIO_BASE, 1U << LED_RED_PIN); PINS_SetPins(LED_GREEN_GPIO_BASE, 1U << LED_GREEN_PIN); PINS_SetPins(LED_BLUE_GPIO_BASE, 1U << LED_BLUE_PIN); //Set pin as output PINS_SetPinDir(LED_RED_GPIO_BASE, LED_RED_PIN, 1U); PINS_SetPinDir(LED_GREEN_GPIO_BASE, LED_GREEN_PIN, 1U); PINS_SetPinDir(LED_BLUE_GPIO_BASE, LED_BLUE_PIN, 1U); } //Pins module initialization button void PINS_Btn_Init(){ //Enable PMC clock CLOCK_SYS_ConfigModuleClock(PMC_CLK, NULL); //Set pin mode PINS_SetMuxModeSel(KEY1_PORT_BASE, KEY1_PIN, PM_MUX_AS_GPIO); PINS_SetMuxModeSel(KEY2_PORT_BASE, KEY2_PIN, PM_MUX_AS_GPIO); //Set pin interrupt PINS_SetPinIntSel(KEY1_PORT_BASE, KEY1_PIN, PM_INT_RISING_EDGE); PINS_SetPinIntSel(KEY2_PORT_BASE, KEY2_PIN, PM_INT_RISING_EDGE); //Set input direction PINS_SetPinDir(KEY1_GPIO_BASE, KEY1_PIN, 0); PINS_SetPinDir(KEY2_GPIO_BASE, KEY2_PIN, 0); PINS_ClrPinInt**Cmd(KEY1_PORT_BASE, KEY1_PIN); PINS_ClrPinInt**Cmd(KEY2_PORT_BASE, KEY2_PIN); } //Main function int main(void){ //Initialize clock CLOCK_SYS_Init(&g_clockConfig); //Led init LED_Init(); PINS_WritePin(LED_GPIO, BLUE_LED_PIN, 1); PINS_WritePin(LED_GPIO, GREEN_LED_PIN, 1); PINS_WritePin(LED_GPIO, RED_LED_PIN, 1); //UART init COM_Init(); //button init PINS_Btn_Init(); //set PMC interrupt callback function INT_SYS_InstallHandler(PMC_IRQn,&KEY_IRQHandler,(ISR_T*) 0); INT_SYS_InstallHandler(SysTick_IRQn,&SysTick_Handler,(ISR_T*) 0); //Enable PMC interrupt INT_SYS_EnableIRQ(PMC_IRQn); INT_SYS_EnableIRQ(SysTick_IRQn); //ADC init ADC_init(); SysTick_Init(); lcdInit();lcdClear();dispBase(); printf("Test G32A1465 lcdDisp adc keyInt and ...\r\n"); while (1){ if(js>999999)js=0;//else js++; //Calculated voltage value Output ADC conversion value adcValue = ADC_readValue()/g_adcMaxValue*g_adcDifference; printf("ADC conversion voltage value = %fV Key=%3d \r\n",adcValue,kk); dispMes(); LED_On(2);SysTick_Delay_ms(1);LED_Off(2); SysTick_Delay_ms(100); } } //end of group ADC_SoftwareConversion_Functions and group ADC_SoftwareConversion and group Examples g32a1xxx_int.c中头部增加的: extern uint32_t js; void SysTick_Handler(void){ js++; OSIF_Tick(); TimingDelay_Decrement(); } 至此实验到此又完成了一个,自定义终端的方法。 照片1是串口输出的采集;照片2是LCD显示js=的蹦字。只能看清千进位的增加,后边的太快看不清此时的技术是准确的,想显示的慢点只需要将显示的内容再除掉1或2或3位即可。 视频链接地址:
|