这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【换取手持数字示波器】+APM32F305调试基本外设功能

共2条 1/1 1 跳转至

【换取手持数字示波器】+APM32F305调试基本外设功能

菜鸟
2024-06-19 19:54:26   被打赏 23 分(兑奖)     打赏

  使用工具:keil5.38a,调试器是使用的自制的DAP调试器;

一:GPIO口操作    

    首先看一下官方SDK里面的驱动文件

1.png

 这里要注意一下啊,对于初学者或者是对汇编了解不是很多的同学来说,启动文件里面的驱动文件不要修改,否则程序可能会导致意想不到问题,我不小心修改了栈大小,导致程序在进入主函数之后,就直接进入了硬件错误。

基本上所有的开发板上面第一个功能介绍是如何创建工程,第二个就是简单介绍IO口的操作,而最直接的就是利用LED灯作为显示,这样能清晰的看到IO口的高低电平。

查看原理图:

2.png

整个电路板只有两个0603封装的LED灯,一个是用来指示电源电路是否正常,另外一个是故障指示灯(PC15),当IO口输出高电平时,指示灯熄灭,输出低电平时,指示灯亮起。

  首先要初始化使用的IO口:

#define LEDn                             2
#define LED2_PIN                         GPIO_PIN_15
#define LED2_GPIO_PORT                   GPIOC
#define LED2_GPIO_CLK                    RCM_AHB_PERIPH_GPIOC
/*GPIO口初始化函数*/
void GPIO_Init(void)
{
    GPIO_Config_T gpioConfig;
/*注意要使能PCIO口的时钟,要不然io口是不会工作的。*/ 
    RCM_EnableAHBPeriphClock(LED2_GPIO_CLK | LED3_GPIO_CLK);   //使能IO口的时钟
    /* LED2 GPIO configuration */
    gpioConfig.pin = LED2_PIN;               //选择相对应的引脚1
    gpioConfig.mode = GPIO_MODE_OUT;            //选择引脚的输出模式
    gpioConfig.outtype = GPIO_OUT_TYPE_PP;         //选择引脚的输出模式
    gpioConfig.speed = GPIO_SPEED_50MHz;          //选择引脚的输出速度                                  
    gpioConfig.pupd = GPIO_PUPD_NO;
    GPIO_Config(LED2_GPIO_PORT, &gpioConfig);        //初始化引脚           
 
    /* LED3 GPIO configuration */    
    gpioConfig.pin = LED3_PIN;               //初始化使用的引脚2                                     
    GPIO_Config(LED3_GPIO_PORT, &gpioConfig);        //初始化引脚 
}
/*系统延时函数*/
void APM_MINI_DelayMs(__IO uint32_t nms)
{
    uint32_t temp;
 
    SysTick->LOAD = (uint32_t)nms * cntMs;
    SysTick->VAL = 0x00;
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
    do
    {
        temp = SysTick->CTRL;
    }
    while ((temp & 0x01) && !(temp & (1 << 16)));
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    SysTick->VAL = 0x00;
}

这里为了显示状态的改变时用了500ms的延时,当然本身这种延时函数是没有问题的,但是以后在工作中不要用类似的延时,很影响程序的运行。试验效果将在下面的视频中展示。

二:外部中断(EINT)简单调试使用

 中断/事件分为内部中断/事件、外部中断/事件。在该手册中,外部中断指从 I/O引脚输入信号引起的中断/事件,在中断向量表中指 EINTx;其它中断指内部中断/事件。事件可分为硬件事件、软件事件。硬件事件是通过外部/内核硬件信号产生事件,软件事件是通过指令产生事件。中断需经过中断处理函数实现需要处理的工作;事件不需要经过中断处理函数,可硬件触发预先设置的工作。外部事件例如可通过事件是 GPIO 输出脉冲,内部事件例如通过一个 TMR 的更新事件触发另一个 TMR 作。这里我们用板载的按键K1(PC14)LED灯(PC15)两个IO口调试这个功能。

3.png

/*中断处理函数*/
void EINT_Init(void)
{
    GPIO_Config_T gpioConfig;
    EINT_Config_T eintConfig;
 
    /* Enable the BUTTON Clock */
    RCM_EnableAHBPeriphClock(KEY1_BUTTON_GPIO_CLK);   //使能按键1的使用IO口的时钟线
    RCM_EnableAHBPeriphClock(KEY2_BUTTON_GPIO_CLK);   //使能按键2的使用IO口的时钟线

    RCM_EnableAPB2PeriphClock(RCM_AHB_PERIPH_GPIOC);  //使能LED灯的使用IO口的时钟线
 
    /* Configure Button pin as input floating */
    gpioConfig.mode = GPIO_MODE_IN;          //设置中断输入口为输入模式
    gpioConfig.pupd = GPIO_PUPD_PU;
    gpioConfig.pin = KEY1_BUTTON_PIN;         //设置中断输入口1的端口号  
    GPIO_Config(KEY1_BUTTON_GPIO_PORT, &gpioConfig);  //初始化按键1的IO 口
 
    gpioConfig.pin = KEY2_BUTTON_PIN;         //设置中断输入口2的端口号 
    GPIO_Config(KEY2_BUTTON_GPIO_PORT, &gpioConfig); //初始化按键1的IO 口
 
    /* Configure GPIO pin used as EINT Line */
    SYSCFG_EINTLine(SYSCFG_PORT_GPIOC, SYSCFG_PIN_14); //配置IO口的中断模式
    SYSCFG_EINTLine(SYSCFG_PORT_GPIOA, SYSCFG_PIN_0);  //配置IO口的中断模式
  
    /* Configure Button exit line */
    eintConfig.line    =  KEY1_BUTTON_EXTI_LINE;  //配置IO口的中断线
    eintConfig.lineCmd =  ENABLE;           //使能IO口的中断线     
    eintConfig.mode    =  EINT_MODE_INTERRUPT;   //配置中断为输入模式
    eintConfig.trigger =  EINT_TRIGGER_FALLING;    //配置中断为下降沿捕获
    EINT_Config(&eintConfig);               //初始化中断口1 
 
    eintConfig.line    =  KEY2_BUTTON_EXTI_LINE;
    EINT_Config(&eintConfig);              //初始化中断口2 
 
    /* Configure NVIC_IRQRequest */
    NVIC_EnableIRQRequest(EINT4_15_IRQn, 0x0F);     //配置中断的优先级为0x0F
}

三:定时器3PWM输出功能调试

    APM32的定时器资源是比较丰富的,由于板子上面只有将PA7引脚引出,查看手册PA7引脚是可以复用定时器3的复用1功能;资料如下图所示:

6.png

void APM_MINI_TMR1_PWMOutPut_Init(void)
{
    TMR_TimeBase_T  timeBaseConfig;
    TMR_OCConfig_T  occonfig;
    GPIO_Config_T   gpioconfig;
 
    /* Enable Clock*/
    RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);

 
    /* Connect TMR1 to CH1 */

    RCM_EnableAPB1PeriphClock(RCM_APB2_PERIPH_SYSCFG);
    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR3);

    /* Connect TMR1 to CH1 */
    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_7, GPIO_AF_PIN1);
    gpioconfig.mode  = GPIO_MODE_AF;
    gpioconfig.outtype = GPIO_OUT_TYPE_PP;
    gpioconfig.pin   = GPIO_PIN_7;
    gpioconfig.pupd  = GPIO_PUPD_NO;
    gpioconfig.speed = GPIO_SPEED_50MHz;
    GPIO_Config(GPIOA, &gpioconfig); 



    /* Set clockDivision = 1 */
    timeBaseConfig.clockDivision = TMR_CKD_DIV1;
    /* Up-counter */
    timeBaseConfig.counterMode = TMR_COUNTER_MODE_UP;
    /* Set divider = 47 .So TMR1 clock freq ~= 48/(47+1) = 1MHZ */
    timeBaseConfig.div = 47 ;
    /* Set counter = 1000 */
    timeBaseConfig.period = 500-1;
    /* Repetition counter = 0x0 */
    timeBaseConfig.repetitionCounter = 0;
    TMR_ConfigTimeBase(TMR3, &timeBaseConfig);
 
    /* PWM1 mode */
    occonfig.OC_Mode = TMR_OC_MODE_PWM2;
    /* Idle State is reset */
    occonfig.OC_Idlestate = TMR_OCIDLESTATE_RESET;
    /* NIdle State is reset */
    occonfig.OC_NIdlestate = TMR_OCNIDLESTATE_RESET;
    /* Enable CH1N ouput */
    occonfig.OC_OutputNState = TMR_OUTPUT_NSTATE_DISABLE;
    /* Enable CH1 ouput */
    occonfig.OC_OutputState = TMR_OUTPUT_STATE_ENABLE;
    /* CH1  polarity is high */
    occonfig.OC_Polarity = TMR_OC_POLARITY_HIGH;
    /* CH1N polarity is high */
    occonfig.OC_NPolarity = TMR_OC_NPOLARITY_HIGH;
    /* Set compare value */
    occonfig.Pulse = 250-1;
    TMR_OC2Config(TMR3, &occonfig);
 
    /* Enable PWM output */
    TMR_EnablePWMOutputs(TMR3);
    /* Enable TMR1  */
    TMR_Enable(TMR3);
}

上述代码是根据例程进行修改。需要修改引脚配置,定时器3的时钟和PWM的输出函数,当所有配置完成后,最后再使能定时器3,实际效果如下图:输出脉冲计算公式:48MHZ/48 =1M1M/500 = 2000  = 2K;占空比修改occonfig.Pulse该项参数;

具体定时时间很好计算,主频是120mhz,然后arrprc199999,所以每次触发的时间就是1ms,之后是定时器的回调函数。

7.png

四:ADC调试过程:APM32内部ADC介绍:12 位精度的 ADC,共 19 个通道, 16 个外部通道和 3 个内部通道, 各通道 A/D转换模式有单次、连续和断续, ADC 转换结果可以左对齐或右对齐存储在 16 位数据寄存器中。 

8.png

void ADC_Init(void)
{
    ADC_Config_T  adcConfig;
    GPIO_Config_T gpioConfig;
    /* RCM Enable*/
    /* RCM Enable*/
    RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
    RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC);
    RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
    /* GPIO Configuration */
    gpioConfig.pin = GPIO_PIN_7;
    gpioConfig.mode = GPIO_MODE_AN;
    gpioConfig.pupd = GPIO_PUPD_PU;
    GPIO_Config(GPIOA, &gpioConfig);
    /* ADC Configuration */
    ADC_Reset();
    ADC_ConfigStructInit(&adcConfig);
    /* Set resolution*/
    adcConfig.resolution    = ADC_RESOLUTION_12B;
    /* Set dataAlign*/
    adcConfig.dataAlign     = ADC_DATA_ALIGN_RIGHT;
    /* Set scanDir*/
    adcConfig.scanDir       = ADC_SCAN_DIR_UPWARD;
    /* Set convMode continous*/
    adcConfig.convMode      = ADC_CONVERSION_CONTINUOUS;
    /* Set extTrigConv*/
    adcConfig.extTrigConv1  = ADC_EXT_TRIG_CONV_TRG7;
    /* Set TrigEdge*/
    adcConfig.extTrigEdge1  = ADC_EXT_TRIG_EDGE_NONE;
 
    ADC_Config(&adcConfig);
    ADC_ConfigChannel(ADC_CHANNEL_7, ADC_SAMPLE_TIME_239_5);
    /* Enable Interrupt*/
    ADC_EnableInterrupt(ADC_INT_CS);
 
    NVIC_EnableIRQRequest(ADC_COMP_IRQn, 2);
 
    /* Enable VREFINT*/
    ADC_EnableVrefint();
 
    /* Calibration*/
    ADC_ReadCalibrationFactor();
    /* Enable ADC*/
    ADC_Enable();
}
 
/*!
 * @brief       ADC interrupt callback
 *
 * @param       None
 *
 * @retval      None
 *
 * @note        This function need to put into ADC_COMP_IRQHandler in apm32f035_int.c
 */
void ADC_Isr(void)
{
    uint32_t adcData = 0;
    float voltage = 0.0;
 
    if (ADC_ReadIntFlag(ADC_INT_FLAG_CS) == SET)
    {
        ADC_ClearIntFlag(ADC_INT_FLAG_CS);
        /* Read ADC Conversion value */
        adcData = ADC_ReadConversionValue();
 
        voltage = ((float)adcData / 4095) * 3300;
 
        /* output to serial port */
        printf("Vref voltage : %.3f mV\r\n", voltage);
 
        APM_MINI_LEDToggle(LED2);
        APM_MINI_DelayMs(500);
    }
}

初始化ADC,并配置PA7为输入模式,更改中断号就可以正常调试;但是内部的ADC调试的时候会存在误差的,我在调试的时候发现,内部AD到不了满值,

  9.png








关键词: APM32F305     外设     GPIO口     ADC     中断    

工程师
2024-06-25 07:56:49     打赏
2楼

谢谢分享。学习了。


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]