1.概述
小华HC32F488系列芯片具备了AOS自动运行系统这个外设功能,啥是AOS自动运行系统呢?难道HC32F488芯片内自带了一个能够自动运行的系统?这个系统并非我们理解上的通过代码实现的类RTOS之类的系统,根据UM手册的定义,自动运行系统(Automatic Operation System)用于在不借助CPU的情况下实现外设之间的联动。由此我想到了DMA,在配置DMA之后,使能DMA就不需要CPU的干预了,可以自动完成DMA配置的任务;其实AOS还真和DMA有相似之处,即在配置AOS功能之后,在不需要CPU干预的情况下,就可以完成我们设定的功能;更直观的说,它就是一个触发,通过触发源来执行触发的任务。在UM手册中也介绍了,利用外设产生的事件作为AOS源(比如定时器的比较匹配、定时器的计数溢出、RTC的周期信号、通信模块的收发数据的各种状态、ADC的转换结束等事件),来触发其它的外设动作。
2.例程
2.1.我们来实现一个通过定时器以固定周期去触发ADC转换功能的示例程序
---在没有使用AOS功能时,我们的实现应该是配置ADC,使能ADC转换完成中断、配置定时器,使能定时器中断、最后使能ADC和定时器,在定时器达到固定周期后,就会触发定时器中断,我们在中断函数中使能ADC转换,等待ADC转换完成后,我们最后进入ADC转换完成中断,以此周而复始。
---当我们使用AOS功能时,我们的实现却变成了:配置ADC,使能ADC转换完成中断,配置定时器、配置AOS,触发源是定时器,触发目标是开始ADC转换,最后使能定时器就完成了;在定时器触发条件达到时,就会自动开始ADC转换,等ADC转换完成后,就进入到ADC转换完成中断了,以些周而复始。
由此可以看出,AOS的使用节省了MCU在代码和处理时间上的开销,更稳定更可靠,更智能!
2.2.配置程序
/* ADC unit instance for this example. */
#define ADC_UNIT (CM_ADC1)
#define ADC_PERIPH_CLK (FCG3_PERIPH_ADC1)
/* Selects ADC channels that needed. */
#define ADC_SEQB_CH (ADC_CH10)
#define ADC_SEQB_CH_PORT (GPIO_PORT_C)
#define ADC_SEQB_CH_PIN (GPIO_PIN_00)
#define ADC_SEQB_HARDTRIG (ADC_HARDTRIG_EVT0)
#define ADC_SEQB_AOS_TRIG_SEL (AOS_ADC1_0)
#define ADC_SEQB_TRIG_EVT (EVT_SRC_TMR0_1_CMP_B)
/* Timer0 for sequence B */
#define TMR0_UNIT (CM_TMR0_1)
#define TMR0_CH (TMR0_CH_B)
#define TMR0_PERIPH_CLK (FCG2_PERIPH_TMR0_1)
#define TMR0_CMP_VAL (31250UL - 1UL)
#define TMR0_CLK_DIV (TMR0_CLK_DIV256)
#define TMR0_PERIPH_ENABLE() FCG_Fcg2PeriphClockCmd(TMR0_PERIPH_CLK, ENABLE)
/* Interrupt */
#define ADC_SEQB_INT_PRIO (DDL_IRQ_PRIO_03)
#define ADC_SEQB_INT_SRC (INT_SRC_ADC1_EOCB)
#define ADC_SEQB_INT_IRQn (INT015_IRQn)
/**
* [url=home.php?mod=space&uid=159083]@brief[/url] Set specified ADC pin to analog mode.
* @param None
* @retval None
*/
static void ADC_InitGPIO(void)
{
stc_gpio_init_t stcGpioInit;
(void)GPIO_StructInit(&stcGpioInit);
stcGpioInit.u16PinAttr = PIN_ATTR_ANALOG;
(void)GPIO_Init(ADC_SEQB_CH_PORT, ADC_SEQB_CH_PIN, &stcGpioInit);
}
/**
* @brief ADC sequence B interrupt callback.
* @param None
* @retval None
*/
static void ADC1_SEQB_IRQCallback(void)
{
uint16_t u16AdcVal;
u16AdcVal = ADC_GetValue(ADC_UNIT, ADC_SEQB_CH);
ADC_ClearStatus(ADC_UNIT, ADC_FLAG_EOCB);
DDL_Printf("ADC sequence B was triggered by TMR0 event.\r\n");
DDL_Printf("ADC value of sequence B channel: %u\r\n", u16AdcVal);
}
/**
* @brief Initializes ADC.
* @param None
* @retval None
*/
static void ADC_Configuration(void)
{
stc_adc_init_t stcAdcInit;
stc_tmr0_init_t stcTmr0Init;
stc_irq_signin_config_t stcIrq;
/* 1. Enable ADC peripheral clock. */
FCG_Fcg3PeriphClockCmd(ADC_PERIPH_CLK, ENABLE);
/* 2. Modify the default value depends on the application. */
(void)ADC_StructInit(&stcAdcInit);
stcAdcInit.u16ScanMode = ADC_MD_SEQA_SEQB_SINGLESHOT;
/* 3. Initializes ADC. */
(void)ADC_Init(ADC_UNIT, &stcAdcInit);
/* 4. ADC channel configuration. */
/* 4.1 Set the ADC pin to analog input mode. */
ADC_InitGPIO();
/* 4.2 Enable ADC channels. */
ADC_ChCmd(ADC_UNIT, ADC_SEQ_B, ADC_SEQB_CH, ENABLE);
/************** Hard trigger of sequence B ****************/
TMR0_PERIPH_ENABLE();
/* Initials TIMER0. */
(void)TMR0_StructInit(&stcTmr0Init);
stcTmr0Init.u32ClockDiv = TMR0_CLK_DIV;
stcTmr0Init.u16CompareValue = (uint16_t)TMR0_CMP_VAL;
(void)TMR0_Init(TMR0_UNIT, TMR0_CH, &stcTmr0Init);
/* Specifies the event defined by 'ADC_SEQB_TRIG_EVT' as the hard trigger of sequence B. */
FCG_Fcg0PeriphClockCmd(FCG0_PERIPH_AOS, ENABLE);
ADC_TriggerConfig(ADC_UNIT, ADC_SEQ_B, ADC_SEQB_HARDTRIG);
AOS_SetTriggerEventSrc(ADC_SEQB_AOS_TRIG_SEL, ADC_SEQB_TRIG_EVT);
ADC_TriggerCmd(ADC_UNIT, ADC_SEQ_B, ENABLE);
stcIrq.enIntSrc = ADC_SEQB_INT_SRC;
stcIrq.enIRQn = ADC_SEQB_INT_IRQn;
stcIrq.pfnCallback = &ADC1_SEQB_IRQCallback;
(void)INTC_IrqSignIn(&stcIrq);
NVIC_ClearPendingIRQ(stcIrq.enIRQn);
NVIC_SetPriority(stcIrq.enIRQn, ADC_SEQB_INT_PRIO);
NVIC_EnableIRQ(stcIrq.enIRQn);
ADC_IntCmd(ADC_UNIT, ADC_INT_EOCB, ENABLE);
}
/**
* @brief Main function of template project
* @param None
* @retval int32_t return value, if needed
*/
int32_t main(void)
{
/* Register write enable for some required peripherals. */
LL_PERIPH_WE(LL_PERIPH_ALL);
/* Initialize BSP system clock. */
BSP_CLK_Init();
/* Initializes UART for debug printing. Baudrate is 115200. */
DDL_PrintfInit(BSP_PRINTF_DEVICE, 115200UL, BSP_PRINTF_Preinit);
/* LED initialize */
LED_Init();
/* Configures ADC. */
ADC_Configuration();
/* Register write protected for some required peripherals. */
LL_PERIPH_WP(LL_PERIPH_ALL);
stc_clock_freq_t stc_clock_freq;
CLK_GetClockFreq(&stc_clock_freq);
DDL_Printf("\r\n");
DDL_Printf("\r\nEV_F448_LQ80_Rev1.0 %s %s", __DATE__, __TIME__);
DDL_Printf("\r\nSYSCLK Frequency : %7.3f MHz", (double)stc_clock_freq.u32SysclkFreq / (double)1000000.0);
DDL_Printf("\r\nHCLK Frequency : %7.3f MHz", (double)stc_clock_freq.u32HclkFreq / (double)1000000.0);
DDL_Printf("\r\nPCLK0 Frequency : %7.3f MHz", (double)stc_clock_freq.u32Pclk0Freq / (double)1000000.0);
DDL_Printf("\r\nPCLK1 Frequency : %7.3f MHz", (double)stc_clock_freq.u32Pclk1Freq / (double)1000000.0);
DDL_Printf("\r\nPCLK2 Frequency : %7.3f MHz", (double)stc_clock_freq.u32Pclk2Freq / (double)1000000.0);
DDL_Printf("\r\nPCLK3 Frequency : %7.3f MHz", (double)stc_clock_freq.u32Pclk3Freq / (double)1000000.0);
DDL_Printf("\r\nPCLK4 Frequency : %7.3f MHz", (double)stc_clock_freq.u32Pclk4Freq / (double)1000000.0);
DDL_Printf("\r\nEXCLK Frequency : %7.3f MHz", (double)stc_clock_freq.u32ExclkFreq / (double)1000000.0);
DDL_Printf("\r\n");
TMR0_Start(TMR0_UNIT, TMR0_CH);
for ( ;; )
{
LED_G_TOGGLE();
DDL_DelayMS(500);
}
}
2.3.运行结果
3.程序附件
替换HC32F448_DDL_Rev1.1.0\projects\ev_hc32f448_lqfp80目录下的template目录内容即可