【电机控制器】FM33LF015芯片——ADC温度传感器


@TOC

前言

使用工具:
1.FM33LF015开发板
2.J-OBV2仿真烧录器
3.USB-TTL
4.上位机串口助手


在这里插入图片描述

提示:以下是本篇文章正文内容,下面案例可供参考

一、概述

亮点:
1.有两个运算放大器,对于电机控制来说是不错的
2.支持DMA
在这里插入图片描述

二、温度传感器计算公式

在这里插入图片描述

三、代码

main.c

float  GetT;
int main(void)
{
    /* Configure the system clock */
    MF_Clock_Init();
    /* Initialize FL Driver Library */
    FL_Init();
    /* Initialize all configured peripherals */
    MF_Config_Init();
        /* 串口0初始化 */
        MF_UART0_Init();
        /* 高级定时器PWM PB7输出 */
        //MF_ATIM_PWM_Config_Init();
        /* 基础定时器1ms */
        MF_BSTIM16_Config_Init();
        /* 看门狗初始化 */
        WDG_Init();
        LED1_OFF();
      /* Initial ADC */
    MF_ADC_Common_Init();                                                               /*ADC基础配置*/
    MF_ADC_Init();   
    while(1)
        {   
                GetT = GetTS_POLL();
                printf("温度 = %3f\n",GetT);  
                WDG_Reset();
                Run_Systimer();
                Function_Deal();
        }
}

mf_adc.c

/* Includes ------------------------------------------------------------------*/

#include "mf_config.h"

/**
  * @brief  ADC_Common Initialization function
  * @param  void
  * @retval None
  */
void MF_ADC_Common_Init(void)
{
    FL_ADC_CommonInitTypeDef    Common_InitStruct;

    Common_InitStruct.clockSource = FL_CMU_ADC_CLK_SOURCE_RCHF;                         /*配置ADC工作时钟源*/
    Common_InitStruct.clockPrescaler = FL_ADC_CLK_PSC_DIV8;                             /*配置ADC工作时钟分配*/
    Common_InitStruct.referenceSource = FL_ADC_REF_SOURCE_VDDA;                         /*配置ADC参考源*/
    Common_InitStruct.bitWidth = FL_ADC_BIT_WIDTH_12B;                                  /*配置ADC输出位宽*/

    (void)FL_ADC_CommonInit(&Common_InitStruct);
}

/**
  * @brief  ADC Initialization function
  * @param  void
  * @retval None
  */
void MF_ADC_Init(void)
{
    FL_ADC_InitTypeDef    ADC_InitStruct;

    ADC_InitStruct.conversionMode = FL_ADC_CONV_MODE_SINGLE;                            /*配置ADC转换模式*/
    ADC_InitStruct.autoMode = FL_ADC_SINGLE_CONV_MODE_AUTO;                             /*配置ADC转换流程,仅对单次转换有效*/
    ADC_InitStruct.waitMode = FL_ENABLE;                                                /*配置ADC等待模式*/
    ADC_InitStruct.overrunMode = FL_ENABLE;                                             /*配置ADC_Overrun模式*/
    ADC_InitStruct.scanDirection = FL_ADC_SEQ_SCAN_DIR_FORWARD;                         /*配置ADC扫描顺序*/
    ADC_InitStruct.externalTrigConv = FL_ADC_TRIGGER_EDGE_NONE;                         /*配置非软件触发使能及极性*/
    ADC_InitStruct.triggerSource = FL_DISABLE;                                          /*配置ADC非软件触发源*/
    ADC_InitStruct.fastChannelTime = FL_ADC_FAST_CH_SAMPLING_TIME_2_ADCCLK;             /*配置ADC快速通道采样时间*/
    ADC_InitStruct.lowChannelTime = FL_ADC_SLOW_CH_SAMPLING_TIME_512_ADCCLK;            /*配置ADC慢速通道采样时间*/
    ADC_InitStruct.oversamplingMode = FL_DISABLE;                                       /*配置ADC过采样模式*/
    ADC_InitStruct.overSampingMultiplier = FL_ADC_OVERSAMPLING_MUL_16X;                 /*配置ADC过采样率*/
    ADC_InitStruct.oversamplingShift = FL_ADC_OVERSAMPLING_SHIFT_4B;                    /*配置ADC过采样结果移位*/

    (void)FL_ADC_Init(ADC, &ADC_InitStruct);

    FL_ADC_EnableSequencerChannel(ADC, FL_ADC_INTERNAL_TS);                             /*通道选择*/
}


static uint8_t GetVREF1P2Sample_POLL(uint32_t *ADCRdresult)
{
    uint32_t counter = 0;
    uint32_t EOC_Flag;
    uint8_t State;
    FL_CMU_SetADCPrescaler(FL_CMU_ADC_PSC_DIV8);                    //配置ADC工作时钟分频
    FL_VREF_EnableVREFBuffer(VREF);                                 //使能VREF BUFFER,
    //为了考虑功耗BUFFER可关闭,从使能到ADC可以正常采样需要100us的建立时间,本例程配置慢速通道较长的采样时间,来保证建立时间满足。
    FL_ADC_DisableSequencerChannel(ADC, FL_ADC_ALL_CHANNEL);        //清空打开的通道
    FL_ADC_EnableSequencerChannel(ADC, FL_ADC_INTERNAL_VREF1P2);    //通道选择

    FL_ADC_ClearFlag_EndOfConversion(ADC);                          //清标志
    FL_ADC_Enable(ADC);                                             //启动ADC
    FL_ADC_EnableSWConversion(ADC);                                 //开始转换

    do
    {
        EOC_Flag = FL_ADC_IsActiveFlag_EndOfConversion(ADC);
        counter++;
    } while((counter != 0xFFFFFFFFU) && (EOC_Flag == 0U));           //等待转换完成

    if(EOC_Flag == 0x01U)
    {
        FL_ADC_ClearFlag_EndOfConversion(ADC);                        //清标志
        *ADCRdresult = FL_ADC_ReadConversionData(ADC);                 //获取采样值

        FL_ADC_Disable(ADC);                                          //关闭ADC
        FL_ADC_DisableSequencerChannel(ADC, FL_ADC_INTERNAL_VREF1P2); //通道关闭
        FL_VREF_DisableVREFBuffer(VREF);                              //关闭VREF BUFFER
        State = 0;
    }
    else
    {
        State = 1 ;
    }

    return State;
}


static uint8_t GetTSSample_POLL(uint32_t *ADCRdresult)
{
    uint32_t counter = 0;
    uint32_t EOC_Flag;
    uint8_t State;

    FL_CMU_SetADCPrescaler(FL_CMU_ADC_PSC_DIV8);                  //配置ADC工作时钟分频
    FL_VREF_EnableVPTATBuffer(VREF);                              //使能PTATBUFFER
    //为了考虑功耗BUFFER可关闭,从使能到ADC可以正常采样需要100us的建立时间,本例程配置慢速通道较长的采样时间,来保证建立时间满足。
    FL_ADC_DisableSequencerChannel(ADC, FL_ADC_ALL_CHANNEL);      //清空打开的通道
    FL_ADC_EnableSequencerChannel(ADC, FL_ADC_INTERNAL_TS);       //通道选择

    FL_ADC_ClearFlag_EndOfConversion(ADC);                        //清标志
    FL_ADC_Enable(ADC);                                           //启动ADC
    FL_ADC_EnableSWConversion(ADC);                               //开始转换

    do
    {
        EOC_Flag = FL_ADC_IsActiveFlag_EndOfConversion(ADC);
        counter++;
    } while((counter != 0xFFFFFFFFU) && (EOC_Flag == 0U));         //等待转换完成

    if(EOC_Flag == 0x01U)
    {
        FL_ADC_ClearFlag_EndOfConversion(ADC);                      //清标志
        *ADCRdresult = FL_ADC_ReadConversionData(ADC);               //获取采样值

        FL_ADC_Disable(ADC);                                        //关闭ADC
        FL_ADC_DisableSequencerChannel(ADC, FL_ADC_INTERNAL_TS);    //通道关闭
        State = 0;
    }
    else
    {
        State = 1 ;
    }

    return State;
}

float GetTS_POLL(void)
{
    uint32_t VPTAT = 0, VPTAT_30 = 0, GetTSSample = 0, GetVREF1P2Sample = 0;
    uint8_t  Get122VSample_State, GetTSample_State;
    float GetTS = 0.00f;

    Get122VSample_State = GetVREF1P2Sample_POLL(&GetVREF1P2Sample);
    GetTSample_State = GetTSSample_POLL(&GetTSSample);

    if((GetVREF1P2Sample != 0) && (Get122VSample_State == 0)  && (GetTSample_State == 0))
    {
        VPTAT = (uint32_t)(((uint64_t)GetTSSample * 3000 * (ADC_VREF)) / ((uint64_t)GetVREF1P2Sample * 4095));
        VPTAT_30 = ((uint32_t)ADC_TS * 3000) / (4095);
        GetTS = ((float)VPTAT - (float)VPTAT_30) / (2.6f) + (30.0f);
    }
    // 转换结果
    return GetTS;
}

四、实验

在这里插入图片描述

五、参考资料

keil 下如何使用printf
【STM32学习】定时器寄存器配置、功能工作过程详解
stm32f103定时器配置与时间计算公式
STM32 TIM(一)定时中断+时钟源选择

总结

本文仅仅简单介绍了【电机控制器】FM33LF015芯片——定时器,评论区欢迎讨论。