注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
lugl4313820的个人空间 https://home.eeworld.com.cn/space-uid-1269709.html [收藏] [复制] [分享] [RSS]
日志

【ACM32G103RCT6开发板测评】tobudOS实现多任务ADC采集

已有 263 次阅读2024-1-9 11:43

【目的】使用tobudOS实现多任务采集ADC

【实验器材】ACM32G103RCT6开发板

【开发软件】MDK5.38、TobudOS

【实现步步骤】

1、复制我的tobudOS工程,重命名为ADCtest

2、在APP中根据官方的例程初始化ADC1通道0、通道1。

/******************************************************************************
* @brief : ADC Polling Mode Initialization.
* @param : none
* @return: none
******************************************************************************/ 
void ADC_Init_Polling_Nchannels(void)
{
    ADC_ChannelConfTypeDef ADC_ChannelConf;

    ADC_Handle.Init.ClockPrescaler = ADC_CLOCK_DIV16;       //ADC_CLK分频选择
    ADC_Handle.Init.Resolution     = ADC_RESOLUTION_12B;    //分辨率
    ADC_Handle.Init.DataAlign      = ADC_DATAALIGN_RIGHT;   //数据对齐
    ADC_Handle.Init.ConConvMode    = DISABLE;               //连续转换模式

    ADC_Handle.Init.DiscontinuousConvMode = DISABLE;        //间断模式
    ADC_Handle.Init.NbrOfDiscConversion   =1;               //间断模式通道计数
    ADC_Handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;  //触发模式:外部触发或软件触发
    ADC_Handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;//外部触发边沿选择
    ADC_Handle.Init.DMAMode = ADC_DMAMODE_DISABLE;          //DMA选择
    ADC_Handle.Init.OverMode = ADC_OVERMODE_DISABLE;        //溢出时是否保留上次采样数据

    ADC_Handle.Init.OverSampMode = ADC_OVERSAMPMODE_DISABLE;//过采样使能
    ADC_Handle.Init.Oversampling.Ratio =ADC_OVERSAMPLING_RATIO_2;//过采样率
    ADC_Handle.Init.Oversampling.RightBitShift =ADC_RIGHTBITSHIFT_2;//过采样移位系数
    ADC_Handle.Init.Oversampling.TriggeredMode =0;          //过采样触发模式    
    ADC_Handle.Init.AnalogWDGEn = ADC_ANALOGWDGEN_DISABLE;  //模拟看门狗
    ADC_Handle.Init.ChannelEn = ADC_CHANNEL_0_EN | ADC_CHANNEL_1_EN ;

    ADC_Handle.Instance = ADC1;  //ADC1

    HAL_ADC_Init(&ADC_Handle);


    /* The total adc regular channels number */
    ADC_Handle.ChannelNum = 2;

    /* Add adc channels */
    ADC_ChannelConf.Channel = ADC_CHANNEL_0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ1;  //转换顺序
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;//采样时间
    ADC_ChannelConf.SingleDiff =  ADC_SINGLE_ENDED;  // ADC_DIFFERENTIAL_ENDED ;    //单端/差分模式
    //offset config
    ADC_ChannelConf.OffsetNumber = ADC_OFFSET_NONE;   //modeString[0].number;  //ADC_OFFSET_NONE;  //偏移通道选择
    ADC_ChannelConf.Offset =  0; //偏移量
    ADC_ChannelConf.OffsetSign = 0; //偏移计算方式
    ADC_ChannelConf.OffsetSaturation = 0;//偏移结果格式选择
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);


    ADC_ChannelConf.Channel = ADC_CHANNEL_1;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ2;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;
    ADC_ChannelConf.SingleDiff = ADC_SINGLE_ENDED;
    ADC_ChannelConf.OffsetNumber = ADC_OFFSET_NONE;
    ADC_ChannelConf.Offset = 0;	
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);

	
}

为了转换电压值我们还需要获取参考电压值:

/******************************************************************************
* @brief : ADC Get The VrefP Value.
* @param : none
* @return: VrefP Value
******************************************************************************/ 
uint32_t ADC_GetVrefP(void)
{
    ADC_HandleTypeDef ADC_Handle_Vrefp;
    ADC_ChannelConfTypeDef ADC_ChannelConf;
    uint32_t TrimValue_3v, AdcValue_VrefP[1], VrefP,temp;
    
    //PMU CLK Enable
    RCC->APB1ENR |= 1<<27;
    //VBG1P2
    *(__IO uint32_t*)(0x400070C0) = 0x05;
    
    HAL_SimpleDelay(2000);
    
    ADC_Handle_Vrefp.Init.ClockPrescaler = ADC_CLOCK_DIV16;       //ADC_CLK分频选择
    ADC_Handle_Vrefp.Init.Resolution     = ADC_RESOLUTION_12B;    //分辨率
    ADC_Handle_Vrefp.Init.DataAlign      = ADC_DATAALIGN_RIGHT;   //数据对齐
    ADC_Handle_Vrefp.Init.ConConvMode    = DISABLE;               //连续转换模式

    ADC_Handle_Vrefp.Init.DiscontinuousConvMode = DISABLE;        //间断模式
    ADC_Handle_Vrefp.Init.NbrOfDiscConversion = 1;                //间断模式通道计数
    ADC_Handle_Vrefp.Init.ExternalTrigConv = ADC_SOFTWARE_START;  //触发模式:外部触发或软件触发
    ADC_Handle_Vrefp.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;//外部触发边沿选择
    ADC_Handle_Vrefp.Init.DMAMode = ADC_DMAMODE_DISABLE;          //DMA选择
    ADC_Handle_Vrefp.Init.OverMode = ADC_OVERMODE_DISABLE;        //溢出时是否保留上次采样数据

    ADC_Handle_Vrefp.Init.OverSampMode = ADC_OVERSAMPMODE_DISABLE;//过采样使能设置
    ADC_Handle_Vrefp.Init.Oversampling.Ratio =ADC_OVERSAMPLING_RATIO_2;//过采样率
    ADC_Handle_Vrefp.Init.Oversampling.RightBitShift =ADC_RIGHTBITSHIFT_2;//过采样移位系数
    ADC_Handle_Vrefp.Init.Oversampling.TriggeredMode =0;          //过采样触发模式    
    ADC_Handle_Vrefp.Init.AnalogWDGEn = ADC_ANALOGWDGEN_DISABLE;  //模拟看门狗
    ADC_Handle_Vrefp.Init.ChannelEn = ADC_CHANNEL_VBGR_EN;

    ADC_Handle_Vrefp.Instance = ADC1;  

    HAL_ADC_Init(&ADC_Handle_Vrefp);

    /* The total adc regular channels number */
    ADC_Handle_Vrefp.ChannelNum = 1;
    
    /* Add adc channels */
    ADC_ChannelConf.Channel = ADC_CHANNEL_VBGR;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ1;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;
    ADC_ChannelConf.SingleDiff = ADC_SINGLE_ENDED;
    ADC_ChannelConf.OffsetNumber = ADC_OFFSET_NONE;
    ADC_ChannelConf.Offset = 0;	
    HAL_ADC_ConfigChannel(&ADC_Handle_Vrefp,&ADC_ChannelConf);
    
    HAL_ADC_Polling(&ADC_Handle_Vrefp, AdcValue_VrefP, ADC_Handle_Vrefp.ChannelNum, 0);
    
    printfS("The adc convert result :  0x%08x[ %d ], VBGR = %dmV\r\n", AdcValue_VrefP[0], AdcValue_VrefP[0] & 0xFFF, ((AdcValue_VrefP[0] & 0xFFF) * 3300 / 4095));
    
    //VBG1P2
    *(__IO uint32_t*)(0x400070C0) &= ~0x05;
    
    TrimValue_3v = *(volatile uint32_t*)(0x00080240); //Read the 1.2v trim value in 3.0v vrefp.

    printfS("The adc 1.2v trim value is : 0x%08x \r\n", TrimValue_3v);

    if(((~TrimValue_3v&0xFFFF0000)>>16) == (TrimValue_3v&0x0000FFFF))
    {
        temp = TrimValue_3v & 0xFFF;
        
        VrefP = (uint32_t)(temp * 3000 / (AdcValue_VrefP[0] & 0xFFF));
      
        return VrefP;
    }
    return 0;
}

我们创建循环触发获取两个通道的ADC程 序

/******************************************************************************
* @brief : ADC Polling Mode test.
* @param : none
* @return: none
******************************************************************************/ 
void ADC_Test_Polling_Nchannels(void)
{
    uint32_t i, VrefP, Voltage;
    
    uint32_t lu32_COM_OK  = 0;

    printfS("The ADC test ADC_Test_Polling_Nchannels start.");
    
    VrefP = ADC_GetVrefP();
    printfS("The VrefP value is : %d \r\n", VrefP);
    
    ADC_Init_Polling_Nchannels();
    
    while(1)
    {
        for (i = 0; i < BUFFER_LENGTH; i++)
        {
            gadcBuffer[i] = 0;
        }

        HAL_ADC_Polling(&ADC_Handle, gadcBuffer, ADC_Handle.ChannelNum, 0);
       
        
        for (i = 0; i < ADC_Handle.ChannelNum; i++)
        {
            printfS("The adc convert result : Channel %d = %d\r\n", gadcBuffer[i]>>16 & 0xFF,gadcBuffer[i]&0xFFF);
            Voltage = (gadcBuffer[i]&0xFFF)*VrefP/4095;
            printfS("The Voltage is: %d mV \r\n", Voltage);
           
        } 
        tos_task_delay(1000);    
    }
}

创建两个任务,一个用于hello 打印,另一个用于ADC的周期采集打印。

#include "main.h"   
#include "app.h"
#include "tos_k.h"

k_task_t task, led_task;

k_stack_t task_stack[1024], task_stack_led[1024];

void test_task(void *Parameter)
{
	while(1)
	{
		printf("hello tobuandOS\r\n");
		tos_task_delay(1000);
	}
}

void led_task_entry(void *Parameter)
{

	ADC_Regular_Channel_Test(ADC_Regular_POLLING);
	

}
/******************************************************************************
*@brief : main program
*@param : none
*@return: none
******************************************************************************/
int main(void)
{
    uint32_t count=0;
	k_err_t err;
	
	HAL_Init();
    SystemClock_Config();
	
    BSP_UART_Init();  	
	BSP_LED_Init();

	tos_knl_init();
	err = tos_task_create(&task, "task1",test_task,NULL, 2, task_stack,1024,20);
	err = tos_task_create(&led_task, "task_led",led_task_entry,NULL, 2, task_stack_led,1024,20);
	tos_knl_start();

}

实现现象,我们把开发板上的A0与VDD相接,A1与GND相接,串口打印效果如下:

====== ACM32G103 MCU is runing ======
SysCoreClk: 120270000Hz, HCLK:120270000Hz
PCLK1:60135000Hz, PCLK2:60135000Hz

Firmware compiled on Jan  9 2024 11:14:52 
hello tobuandOS
The ADC test ADC_Test_Polling_Nchannels start.The adc convert result :  0x001105c2[ 1474 ], VBGR = 1187mV
The adc 1.2v trim value is : 0xf9b5064a 
The VrefP value is : 3276 
The adc convert result : Channel 0 = 4095
The Voltage is: 3276 mV 
The adc convert result : Channel 1 = 0
The Voltage is: 0 mV 
hello tobuandOS
The adc convert result : Channel 0 = 4095
The Voltage is: 3276 mV 
The adc convert result : Channel 1 = 0
The Voltage is: 0 mV 
hello tobuandOS

【讨论】不知道是总线频率的问题还是怎么样,我使用主频为180MHz时初始化ADC是失败的,但是用官方的例程跑为120MHz是可以的。还需要分析一下ADC时钟。

本文来自论坛,点击查看完整帖子内容。

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章