查看: 57974|回复: 5

FM33LC046N评测+ADC采集报警

[复制链接]

217

主题

393

帖子

3477

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3477
QQ
发表于 2021-3-15 22:01:23 | 显示全部楼层 |阅读模式
FM33LC046N评测+ADC采集报警

原帖地址:http://bbs.eeworld.com.cn/thread-1159028-1-1.html


一、ADC概述

FM33LC0XX 带有 1Msps 12bit SAR-ADC,可实现温度、电池电压或其他直流信号的测量功能。 主要特点为:

    1、工作电压 1.8~5.5V
    2、输入信号幅度 0~VDDA
    3、最高采样率 1Msps(FADC=16Mhz)
    4、16 个单端输入通道,包含温度传感器、内部基准电压、运放输出 x2、 12 个外部通道
    5、8 个外部快速通道, 8 个低速通道
    6、可配置的采样保持时间
    7、支持单次转换和连续转换
    8、支持 DMA
    9、支持过采样硬件平均,最高 16bit 输出(256 次平均)

二、结构框图

ADC11.JPG


三、输入通道

输入通道.JPG

四、功能描述之采样值与实际电压的转换


    ADC一般使用电源电压作为基准电压,在电源电压发生变化时,特定输入信号电平对应的转换值也会发送变化,为了能够得到准确的绝对电压,文档中接收的解决方案如下:

    芯片出厂时在Vdd=3V的情况下,测量VREFINT的电压并保存在Flash中

    1、以上条件下,使用ADC转换VREFINT输出,得到转换值VREFINT_CAL并保存在芯片中;

    2、芯片实际应用中,由于不知道当前VDDA电压,ADC先测量VREFINT得到转换值VREFINT_DATA;通过以下公式可以得到当前实际的VDDA;


    假设ADC对某个输入通道的采样值为ADC_DATA,通过以下公式可以得到当前某个输入通道的实际电压(12bit 输出)

公式1.JPG
     采用这个方式,不需要知道每颗芯片VREFINT的实际电压值,仅需计算当前VREFINT采样值和出厂测试值的比例;


公式二.JPG

    VREF1p2 采样的软件配置方法

    1、软件使用 ADC 采样 VREF1p2 时,需要按照以下步骤:
    2、置位 VREF_EN 寄存器,使能 VREF1p2 模块
    3、置位 BUFFERCTRL.VREFBUFFER_EN,使能 VREF 输出 BUFFER
    4、等待 VREF 建立,通过查询 VREF_RDY 寄存器,或通过 VREF_IF 中断
    5、使能 ADC 的 REFCH 通道
    6、使能 ADC 开始转换

五、软件实现步骤

1、ADC初始化

  1. void MF_ADC_Init(void)
  2. {

  3.     FL_GPIO_InitTypeDef    GPIO_InitStruct;

  4.     FL_ADC_InitTypeDef    defaultInitStruct;

  5.     GPIO_InitStruct.pin = FL_GPIO_PIN_9;  //PC9   ADC_IN0
  6.     GPIO_InitStruct.mode = FL_GPIO_MODE_ANALOG;
  7.     GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
  8.     GPIO_InitStruct.pull = DISABLE;
  9.     GPIO_InitStruct.remapPin = DISABLE;

  10.     FL_GPIO_Init( GPIOC, &GPIO_InitStruct );

  11.     defaultInitStruct.conversionMode = FL_ADC_CONV_MODE_SINGLE;//联系转换模式      ,单次转换
  12.     defaultInitStruct.autoMode = FL_ADC_SINGLE_CONV_MODE_AUTO;//单次转换半自动模式,   自动模式
  13.     defaultInitStruct.waitMode = ENABLE;                //等待模式控制,    等待模式
  14.     defaultInitStruct.overrunMode = ENABLE;                //覆盖上次数据
  15.     defaultInitStruct.scanDirection = FL_ADC_SEQ_SCAN_DIR_BACKWARD;//反向扫描ADC_IN11-->ADC_IN0
  16.     defaultInitStruct.externalTrigConv = FL_ADC_TRIGGER_EDGE_NONE;//禁止触发信号使能和极性选择
  17.     defaultInitStruct.triggerSource = FL_ADC_TRGI_PA8;  //硬件触发源  pA8
  18.     defaultInitStruct.fastChannelTime = FL_ADC_FAST_CH_SAMPLING_TIME_4_ADCCLK;  //快速通道采样时间控制  4
  19.     defaultInitStruct.lowChannelTime = FL_ADC_SLOW_CH_SAMPLING_TIME_192_ADCCLK;//慢速通道采样时间控制192
  20.     defaultInitStruct.oversamplingMode = ENABLE;//过采样使能
  21.     defaultInitStruct.overSampingMultiplier = FL_ADC_OVERSAMPLING_MUL_16X;//过采样率控制  16x
  22.     defaultInitStruct.oversamplingShift = FL_ADC_OVERSAMPLING_SHIFT_4B;//过采样移位配置

  23.     FL_ADC_Init(ADC,&defaultInitStruct );
  24. }

  25. void MF_ADC_Common_Init(void)
  26. {

  27.     /*IO CONFIG*/
  28.     FL_ADC_CommonInitTypeDef    CommonInitStruct;

  29.     CommonInitStruct.clockSource = FL_RCC_ADC_CLK_SOURCE_RCHF;
  30.     CommonInitStruct.clockPrescaler = FL_RCC_ADC_PSC_DIV8;

  31.     FL_ADC_CommonInit(&CommonInitStruct );
  32.     FL_ADC_EnableIT_EndOfConversion(ADC );   
  33. }

  34. void MF_NVIC_Init(void)
  35. {
  36.         InterruptConfigStruct.preemptPriority = 1;                //ADC中断优先级
  37.     NVIC_Init(&InterruptConfigStruct,ADC_IRQn );
  38. }
复制代码

2、ADC转换函数

  1. #define ADC_VREF    (*((uint16_t *)(0x1FFFFB08)))   // 30℃ vref1.22采样值

  2. static uint32_t GetVREF1P2Sample_IT(void)
  3. {
  4.         uint16_t ADCRdresult;
  5.         uint8_t i=0;
  6.         FL_RCC_SetADCPrescaler(FL_RCC_ADC_PSC_DIV8);
  7.     FL_VREF_EnableVREFBuffer(VREF);//使能VREF BUFFER
  8.         FL_ADC_EnableSequencerChannel(ADC, FL_ADC_INTERNAL_VREF1P2);//通道选择VREF
  9.                         
  10.         FL_ADC_ClearFlag_EndOfConversion(ADC);//清标志                        
  11.         FL_ADC_Enable(ADC);            // 启动ADC
  12.         FL_ADC_EnableSWConversion(ADC);  // 开始转换
  13.     // 等待转换完成
  14.         while (ADCComplete == 0)
  15.         {
  16.                 if(i>=5)
  17.                 {
  18.                         break;
  19.                 }
  20.                 i++;
  21.                 DelayMs(1);
  22.         }
  23.         ADCComplete = 0;
  24.         FL_ADC_ClearFlag_EndOfConversion(ADC);//清标志
  25.         ADCRdresult =FL_ADC_ReadConversionData(ADC);//获取采样值

  26.   FL_ADC_Disable(ADC);    // 关闭ADC
  27.         FL_ADC_DisableSequencerChannel(ADC, FL_ADC_INTERNAL_VREF1P2);//通道关闭VREF        
  28.   FL_VREF_DisableVREFBuffer(VREF);//关闭VREF BUFFER                        
  29.     // 转换结果
  30.   return ADCRdresult;
  31. }

  32. static uint32_t GetSingleChannelSample_IT(uint32_t channel)
  33. {
  34.         uint16_t ADCRdresult;
  35.         uint8_t i=0;
  36.         FL_RCC_SetADCPrescaler(FL_RCC_ADC_PSC_DIV1);
  37.         FL_ADC_EnableSequencerChannel(ADC, channel);//通道选择

  38.         FL_ADC_ClearFlag_EndOfConversion(ADC);//清标志                        
  39.         FL_ADC_Enable(ADC);            // 启动ADC
  40.         FL_ADC_EnableSWConversion(ADC);  // 开始转换
  41.     // 等待转换完成
  42.         while (ADCComplete == 0)
  43.         {
  44.                 if(i>=5)
  45.                 {
  46.                         break;
  47.                 }
  48.                 i++;
  49.                 DelayMs(1);
  50.         }
  51.         ADCComplete = 0;
  52.         FL_ADC_ClearFlag_EndOfConversion(ADC);//清标志
  53.         ADCRdresult =FL_ADC_ReadConversionData(ADC);//获取采样值

  54.     FL_ADC_Disable(ADC);    // 关闭ADC
  55.         FL_ADC_DisableSequencerChannel(ADC, channel);//通道                  
  56.     // 转换结果
  57.     return ADCRdresult;
  58. }

  59. uint32_t GetSingleChannelVoltage_IT(uint32_t channel)
  60. {
  61.         uint32_t Get122VSample,GetChannelVoltage;
  62.         uint64_t GetVSample;
  63.         
  64.         Get122VSample = GetVREF1P2Sample_IT();
  65.         GetVSample =GetSingleChannelSample_IT(channel);
  66.         GetChannelVoltage =  (GetVSample *3000*(ADC_VREF))/(Get122VSample*4095);
  67.     // 转换结果
  68.     return GetChannelVoltage;
  69. }
复制代码

3、数据采集报警处理

  1. GetVoltage = GetSingleChannelVoltage_IT(FL_ADC_EXTERNAL_CH0 );//获取AD值转换结果
  2. //事件处理
  3. if(uc_secondflag==1)//定时器1s中断
  4. {
  5.         uc_secondflag=0;
  6.         if(GetVoltage>0xA00)
  7.         {
  8.                 printf("警告:AD值大于0xA00=2560  当前AD值 = %x\n",GetVoltage);
  9.                 FL_GPIO_ResetOutputPin(GPIOC,FL_GPIO_PIN_0);//点亮 LED0
  10.         }
  11.         else
  12.         {
  13.                 printf("PC9  ADC =%x\n",GetVoltage);
  14.                 FL_GPIO_SetOutputPin(GPIOC,FL_GPIO_PIN_0);//熄灭   LED0
  15.         }
  16. }
复制代码

adc报警.jpg


硬件.jpg





回复

使用道具 举报

217

主题

393

帖子

3477

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3477
QQ
 楼主| 发表于 2021-3-15 22:04:23 | 显示全部楼层
关于ADC的使用,大家可以参考FM33LC0xxN的ADC应用笔记
链接:http://www.fmdevelopers.com.cn/f ... &extra=page%3D1
回复

使用道具 举报

0

主题

2

帖子

26

积分

初级工程师

Rank: 1

积分
26
发表于 2021-4-20 14:44:08 | 显示全部楼层
wangpeng 发表于 2021-3-15 22:04
关于ADC的使用,大家可以参考FM33LC0xxN的ADC应用笔记
链接:http://www.fmdevelopers.com.cn/forum.php?mo ...

这款开发板在哪里可以购买呢
回复

使用道具 举报

154

主题

846

帖子

4624

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
4624
发表于 2021-4-22 08:27:01 | 显示全部楼层
zhousir 发表于 2021-4-20 14:44
这款开发板在哪里可以购买呢

关于开发板和仿真器
您这边可以加一下 Q 974170020
回复

使用道具 举报

0

主题

2

帖子

26

积分

初级工程师

Rank: 1

积分
26
发表于 2021-4-22 08:46:18 | 显示全部楼层
顾博文 发表于 2021-4-22 08:27
关于开发板和仿真器
您这边可以加一下 Q 974170020

加了,一直没人通过
回复

使用道具 举报

154

主题

846

帖子

4624

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
4624
发表于 2021-4-23 08:39:30 | 显示全部楼层
你联系下 陈工 15365100398 微信同号 ,最近开发板很紧张,可能需要等1,2周才能拿到。你先去问下,有没有现货。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表