使用工具:keil5.38a,调试器是使用的自制的DAP调试器;
一:GPIO口操作
首先看一下官方SDK里面的驱动文件

这里要注意一下啊,对于初学者或者是对汇编了解不是很多的同学来说,启动文件里面的驱动文件不要修改,否则程序可能会导致意想不到问题,我不小心修改了栈大小,导致程序在进入主函数之后,就直接进入了硬件错误。
基本上所有的开发板上面第一个功能介绍是如何创建工程,第二个就是简单介绍IO口的操作,而最直接的就是利用LED灯作为显示,这样能清晰的看到IO口的高低电平。
查看原理图:

整个电路板只有两个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口调试这个功能。

/*中断处理函数*/
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
}三:定时器3的PWM输出功能调试
APM32的定时器资源是比较丰富的,由于板子上面只有将PA7引脚引出,查看手册PA7引脚是可以复用定时器3的复用1功能;资料如下图所示:

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 =1M;1M/500 = 2000 = 2K;占空比修改occonfig.Pulse该项参数;
具体定时时间很好计算,主频是120mhz,然后arr好prc是199和999,所以每次触发的时间就是1ms,之后是定时器的回调函数。

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

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到不了满值,

我要赚赏金
