前言 上一篇我们使用DAC测试了模拟量信号发生,本芯片的ADC参数也不错, 2Msps 12bit SAR-ADC这在通用MCU中也是比较优秀的。我们这一篇就来使用ADC采集信号发送到上位机实现虚拟示波器的功能。 过程引脚使用PD1作为ADC输入 ADC1
初始化
MF_ADC_Common_Init(); /*ADC基础配置*/
MF_ADC_Init(); /*ADC初始化配置*/
static 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);
}
static void MF_ADC_Init(void)
{
FL_GPIO_InitTypeDef GPIO_InitStruct;
FL_ADC_InitTypeDef ADC_InitStruct;
GPIO_InitStruct.pin = FL_GPIO_PIN_1; /*配置GPIO的引脚号*/
GPIO_InitStruct.mode = FL_GPIO_MODE_ANALOG; /*配置GPIO的功能模式*/
GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL; /*配置GPIO的输出模式*/
GPIO_InitStruct.pull = FL_DISABLE; /*配置GPIO输上拉模式*/
GPIO_InitStruct.remapPin = FL_DISABLE; /*配置GPIO数字重定向功能*/
GPIO_InitStruct.analogSwitch = FL_DISABLE; /*配置GPIO模拟开关功能*/
(void)FL_GPIO_Init(GPIOD, &GPIO_InitStruct); /*GPIO初始化*/
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_EXTERNAL_CH1); /*通道选择*/
FL_ADC_EnableSequencerChannel(ADC, FL_ADC_INTERNAL_VREF1P2);
}
采集
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 GetSingleChannelSample_POLL(uint32_t channel, uint32_t *ADCRdresult)
{
uint32_t counter = 0;
uint32_t EOC_Flag;
uint8_t State;
FL_CMU_SetADCPrescaler(FL_CMU_ADC_PSC_DIV1); //配置ADC工作时钟分频
FL_ADC_DisableSequencerChannel(ADC, FL_ADC_ALL_CHANNEL); //清空打开的通道
FL_ADC_EnableSequencerChannel(ADC, channel); //通道选择
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, channel); //通道关闭
State = 0;
}
else
{
State = 1 ;
}
return State;
}
uint32_t GetSingleChannelVoltage_POLL(uint32_t channel)
{
uint32_t Get122VSample = 0, GetChannelVoltage = 0, GetVSample = 0;
uint8_t Get122VSample_State, GetVSample_State;
Get122VSample_State = GetVREF1P2Sample_POLL(&Get122VSample);
GetVSample_State = GetSingleChannelSample_POLL(channel, &GetVSample);
if((Get122VSample != 0) && (Get122VSample_State == 0) && (GetVSample_State == 0))
{
GetChannelVoltage = (uint32_t)(((uint64_t)GetVSample * 3000 * (ADC_VREF)) / ((uint64_t)Get122VSample * 4095)); //计算通道电压
}
return GetChannelVoltage;
}
测试基于上一篇adc的基础上 使用DAC作为信号源输出正弦波,adc采集通过串口打印
int main(void)
{
/* Configure the system clock */
MF_Clock_Init();
/* Initialize FL Driver Library */
FL_Init();
/* Initialize all configured peripherals */
MF_Config_Init();
FL_DelayMs(3000);//32768 起振时间典型时间1S,最大3S
FL_CDIF_EnableVAOToCPU(CDIF);//32768信号从VAO传输到CPU
FL_LPUART_EnableRX(LPUART0);
FL_LPUART_EnableTX(LPUART0);
//FL_LPUART_WriteTXBuff(LPUART0, 0x55);
xdev_out(xprintf_out);
xdev_in(xprintf_in);
dac_init();
MF_ADC_Common_Init(); /*ADC基础配置*/
MF_ADC_Init(); /*ADC初始化配置*/
uint32_t GetVoltage;
while(1)
{
//for(uint32_t i=0;i<4096/100;i++)
//{
// dac_write(i*100);
//}
for(uint32_t i=0;i<360;i++)
{
dac_write(_sin(i/57.29577951307855)*4096/3.3 + 2047);
GetVoltage = GetSingleChannelVoltage_POLL(FL_ADC_EXTERNAL_CH1);
xprintf("/* %d */rn",GetVoltage);
}
}
}
可以看到打印信息如下
虚拟示波器上面我们已经采集到了adc数据并通过串口打印出来,只需要通过上位机接收打印的数据通过曲线显示出来既可以实现虚拟示波器了。 这里的上位机我们使用Serial Studio 可以从这里下载安装https://serial-studio.github.io/ 打开该软件 打开JSON编辑器
设置参数,添加数据组
添加数据
配置参数并保存
保存项目 连接串口控制台显示打印信息
点击仪表盘显示图形
可以调整点数放大缩小
总结基于官方比较完备的库文件,能很快的实现外设模块的操作,比如ADC和DAC,以上基于DAC实现了信号发生器,基于ADC实现了虚拟示波器,实现了串口的通讯通路。 并实现可视化演示,初步具备虚拟示波器和信号发生器的雏形,后面可以再优化操作逻辑,完善显示界面,优化通讯协议等就可以实现基本具备实用性的小工具了。
|