一、程序流程说明
  程序中使用了嵌入式实时操作系统FreeRTOS,如果以前没有使用过嵌入式实时操作系统(RTOS)的同学,阅读或修改代码的时候可能会有点吃力。带RTOS的编程方式和传统的不带操作系统的编程还是有很大的区别的,如果已经接触STM32编程有段时间的同学,可以去学习一下RTOS,如果在一些较为复杂的项目中,使用RTOS进行编程会相对简单一些。推荐可以学习FreeRTOS,这个操作系统是完全开源并且免费的。
/************************************************* main函数说明 ************************************************/

int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//中断分组4RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO复用时钟GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//关闭jtag,使能SWD,可以用SWD模式调试 这两句话非常重要,因为开发板中的按键和EEPROM中的引脚和JTAG引脚复用DBGMCU->CR  &= ~((uint32_t)1<<5);   //关闭异步调试模式 不加这两句的话 PA15 PB3 PB4输出没问题 输入的话 恒为低电平!!!!AFIO->MAPR = (AFIO->MAPR & ~((uint32_t)0x7 << 24)) | (2 << 24);     /*  PA15 PB3 PB4 */delay_init();     //初始化延时函数LED_Init();            //初始化ledKEY_Init();         //按键初始化Display_Init();  //显示初始化Menu_Init();         //菜单初始化MY_ADC_Init();   //ADC初始化MYTIMER_Init(); //定时器初始化DO_Init();AD9850_Init();AT24CXX_Init();//创建开始任务xTaskCreate((TaskFunction_t )start_task,            //任务函数(const char*    )"start_task",          //任务名称(uint16_t       )START_STK_SIZE,        //任务堆栈大小(void*          )NULL,                  //传递给任务函数的参数(UBaseType_t    )START_TASK_PRIO,       //任务优先级(TaskHandle_t*  )&StartTask_Handler);   //任务句柄              vTaskStartScheduler();          //开启任务调度
}

main函数中先是设定中断分组,然后禁用JTAG开启了SWD(因为引脚冲突),在之后初始化一些需要用到的外设,最后创建开始任务再开启FreeRTOS(就是开启任务调度)。main函数比较简单就是开启了一些外设和系统初始化。

/************************************************* start_task说明 ************************************************/

void start_task(void *pvParameters)
{/********* cpu使用率统计功能 **********/#if (usercfgCPU_USAGE_CALCULATE==1)uTaskCPUUsageInit();  //不可以在临界区内调用
//  此种方法计算CPU使用率的原理为:
//  1、在系统启动后,所有用户任务都未开始运行时,统计一段时间T(如1s)内空闲任务被调用的次数M,此时可认为这个次数是CPU占用率最小(接近0)时能够调用空闲任务的最大次数。
//  2、任务开始运行后,在滴答时钟中断处理函数中,每隔T时间,记录空闲任务被调用的次数m。
//  3、CPU占用率为:(1-m/M)*100%#endiftaskENTER_CRITICAL();           //进入临界区/************** 创建BASIC任务 ***************/xTaskCreate((TaskFunction_t )basic_task,       (const char*    )"bac",       (uint16_t       )BASIC_STK_SIZE, (void*          )NULL,             (UBaseType_t    )BASIC_TASK_PRIO,   (TaskHandle_t*  )&BASICTask_Handler);/************** 创建MENU任务 ***************/xTaskCreate((TaskFunction_t )menu_task,       (const char*    )"meu",       (uint16_t       )MENU_STK_SIZE, (void*          )NULL,              (UBaseType_t    )MENU_TASK_PRIO,    (TaskHandle_t*  )&MENUTask_Handler); /************** 创建MAESURE任务 ***************/xTaskCreate((TaskFunction_t )measure_task,         (const char*    )"CAL",       (uint16_t       )MEASURE_STK_SIZE, (void*          )NULL,               (UBaseType_t    )MEASURE_TASK_PRIO, (TaskHandle_t*  )&MEASURETask_Handler); Key_QueueHandle = xQueueCreate(KEY_QUEUELEN,KEY_QUEUESIZE); /* 创建key消息队列 */while(Key_QueueHandle == NULL); /* 队列创建不成功 */Measure_SemaphoreHandle = xSemaphoreCreateCounting( MEASURE_MAXCOUNT, MEASURE_INITCOUNT );//创建measure_task信号量while(Measure_SemaphoreHandle == NULL);Read_Gain(); //读取EEPROM中的增益数据vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}

start_task任务中主要是进行其他任务、信号量、消息队列的创建,可以看到分别创建了basic_task、menu_task、measure_task三个任务,三个任务的具体内容会在下文进行说明。创建了句柄为Key_QueueHandle的消息队列,用来向menu_task任务发送key消息,按键扫描在basic_task中进行,任务间的消息传递用消息队列实现。创建了句柄为Measure_SemaphoreHandle的计数型信号量,这个信号量用于任务同步,每当ADC采集完成了一组数据之后,发送这个信号量给measure_task任务,这个任务主要进行数据的计算和判断。Read_Gain函数读取保存的校准参数,之后删除开始任务(开始任务主要就是创建其他任务,创建完成之后就用不到了,进行删除。)
       usercfgCPU_USAGE_CALCULATE宏定义用于开启CPU使用率统计,FreeRTOS是没有CPU使用率统计功能的,这个功能是我额外加入的,开启这个宏就可以查看CPU的使用率统计了。一般调试的时候可以开启,正式程序发布之后关闭这个功能(这个功能还是会占用CPU使用率的)。

关于如何在FreeRTOS中添加CPU使用率统计功能,可以参考这篇博客:
https://blog.csdn.net/wenyuexunyin/article/details/68937150

二、basic_task任务分析

void basic_task(void *pvParameters)
{uint8_t i = 0,key;Measure_Rs.R6_value = 3015;   //电阻值根据实际值填写 电阻精度较差时可用万用表测量之后填写精确值Measure_Rs.R8_value = 20150;Measure_Rs.R40_value = 1000;Measure_Rs.R42_value = 3000;if(Measure_Dc.dc_gain == 0)Measure_Dc.dc_gain = 40;//设为默认4.0while(1){i++;fptx_rand++;//用于随机选择幅频曲线显示if(i == 100){i = 0;LED0 = !LED0; //run灯闪}key = KEY_Scan(0); /* 按键扫描 */if(key != 0) /* 有按键按下了 */{if(Current_Menu == NULL) //界面{if((key == KEY0_PRES) && (device_mode == DEVICE_MODE_MEASURE)) //测量模式 向上键{Measure_data.data_reg.Measure = 1;//开始测量DC_OFFSET_MEASURE();//测直流偏置vTaskDelay(100);measure_sta = MEASURE_DC_STA; //测量直流偏置}else if(key == KEY1_PRES)//向下键{if(device_mode == DEVICE_MODE_MEASURE){device_mode = DEVICE_MODE_JUDGE; //判断Measure_data.data_reg.Measure = 1;//开始测量DC_OFFSET_MEASURE();//测直流偏置vTaskDelay(100);measure_sta = MEASURE_DC_STA; //测量直流偏置}elsedevice_mode = DEVICE_MODE_MEASURE; //测量DDS_reg.fre_num = 1000;DDS_reg.fre_sta = 1;Display_Clear();}}if(Key_QueueHandle != NULL){xQueueSend(Key_QueueHandle,&key,0);}}//DDS频率变化if(DDS_reg.fre_sta == 1){DDS_reg.fre_sta = 0;ad9850_wr_serial(0x00,DDS_reg.fre_num);//改变频率输出}vTaskDelay(10);}
}

basic_task任务中主要进行一些基本工作,比如运行指示灯、按键扫描、改变DDS频率输出,本任务10ms会被调用一次。
       key1进行模式切换,一个是测量模式,一个是判断模式,测量模式下按下key0按键进行一次数据测量。如果按键被按下,就会将按下按键的键值插入创建的消息队列进行发送。

三、menu_task任务分析

void menu_task(void *pvParameters)
{uint8_t key_que,que_res;while(1){que_res = xQueueReceive( Key_QueueHandle,&key_que,50); /* 等key消息50ms */if(que_res == pdTRUE){Menu_Handler(key_que);Menu_Display();}else{Main_Display();//主界面显示}}
}

menu_task任务主要是处理显示一块的任务,Menu_Handler(key_que); Menu_Display();两个函数主要是处理菜单显示和菜单操作逻辑的,实现菜单结构,这里不做详细的分析,有兴趣的同学可以仔细研究一下菜单实现的原理(后续有空的话写一篇讲讲实现多级菜单的方法,为自己挖个坑。)。菜单中的任务函数会进行装置的校准,根据选择进入不同的菜单,进行不同参数的校准,校准的过程会在后面的博客中进行详细分析。
       Main_Display()函数主要是主界面的显示,测量模式下显示测量的数据,故障判断模式下显示电路的故障种类。

四、measure_task任务分析

void measure_task(void *pvParameters)
{uint8_t cal_res;while(1){xSemaphoreTake(Measure_SemaphoreHandle,portMAX_DELAY); //死等信号量if(measure_sta != MEASURE_NONE_STA) //需要测量{switch(measure_sta) //根据状态来采样{case(MEASURE_DC_STA): //测量直流偏置电压cal_res = DC_Cal_Handle();if(cal_res == 1) //直流偏置电压计算完成{Measure_data.data_reg.Dc_sta = 1; //DC测量完毕Measure_data.Dc = Measure_Dc.dc_value;measure_sta = MEASURE_NONE_STA;//停止采样/***************** 测量输入电阻 ******************/R6_MEASURE_UI2_IN();//切继电器 接入R6Measure_Rs.Rs_Ri_sta = 0;//R6DDS_reg.fre_num = 1000;ad9850_wr_serial(0x00,DDS_reg.fre_num);//1K 默认输出vTaskDelay(200);//延时 等待继电器切换memset(&Measure_Ri_Jun,0,sizeof(Measure_Ri_Jun));//清空缓存Measure_Dc.dc_sample_count = 0;measure_sta = MEASURE_RI_STA; //测量输入电阻Measure_Dc.dc_sample_count = 0;}break;case(MEASURE_RI_STA): //测量输入电阻if(DDS_reg.fre_num == 1000) //1Kcal_res = Ri_Cal_1KHz_Handle();if(cal_res == 1) //直流输入电阻计算完成{Measure_data.data_reg.Ri_sta = 1; //输入电阻测量完毕measure_sta = MEASURE_NONE_STA;//停止采样/***************** 测量输出电阻 ******************/MEASURE_UO1_OUT();//Uo1Measure_Rs.Rs_Ro_sta = 1;//R42DDS_reg.fre_num = 1000;ad9850_wr_serial(0x00,DDS_reg.fre_num);//1K 默认输出vTaskDelay(200);//延时 等待继电器切换if(DDS_reg.fre_num == 1000) //1Kmemset(&Measure_Ri_Jun,0,sizeof(Measure_Ri_Jun));//清缓存measure_sta = MEASURE_RO_STA; //测量输出电阻}break;case(MEASURE_RO_STA): //测量输出电阻if(DDS_reg.fre_num == 1000) //1Kcal_res = Ro_Cal_1KHz_Handle();if(cal_res == 1) //直流输出电阻计算完成{Measure_data.data_reg.Ro_sta = 1; //输出电阻测量完毕measure_sta = MEASURE_NONE_STA;//停止采样/***************** 测量增益 ******************/AV_MEASURE_UO_IN() ;//切继电器 UiDDS_reg.fre_num = 1000;ad9850_wr_serial(0x00,DDS_reg.fre_num);//1K 默认输出vTaskDelay(200);//延时 等待继电器切换if(DDS_reg.fre_num == 1000) //1Kmemset(&Measure_Ro_Jun,0,sizeof(Measure_Ro_Jun));//清缓存measure_sta = MEASURE_AV_STA; //测量增益}break;case(MEASURE_AV_STA): //测量增益if(DDS_reg.fre_num == 1000) //1Kcal_res = Av_Cal_1KHz_Handle();if(cal_res == 1) //直流增益计算完成{if(device_mode == DEVICE_MODE_MEASURE) //测量模式{Measure_data.data_reg.Av_sta = 1; //增益测量完毕measure_sta = MEASURE_FPTX_STA; //测量幅频特性//这里需要将里面的缓存里的数据显示出XY图fptx_bmp_sta = fptx_rand%3;FPTX_MEASURE();//幅频特性/***************** 测量幅频特性 ******************/memset(&Measure_Av_Jun,0,sizeof(Measure_Av_Jun));//清缓存DMA_Cmd(DMA2_Channel5,ENABLE);//使能}else //故障判断模式{measure_sta = MEASURE_NONE_STA; //不测量if(Judge_5K_Av_Sta == 0)//5K增益没测DDS_reg.fre_num = 5000; //5kelseDDS_reg.fre_num = 200000; //200kDDS_reg.fre_sta = 1; //改变频率FPTX_MEASURE() ;//切继电器 幅频特性vTaskDelay(50);//延时 等待继电器切换 和增益继电器一样不用等待/***************** 测量幅频特性 ******************/memset(&Measure_Av_Jun,0,sizeof(Measure_Av_Jun));//清缓存DMA_Cmd(DMA2_Channel5,ENABLE);//使能measure_sta = MEASURE_FPTX_STA; //测量幅频特性}}break;case(MEASURE_FPTX_STA): //测量幅频特性if(device_mode == DEVICE_MODE_MEASURE){cal_res = FPTX_Cal_Scan_Handle();//扫描法if(cal_res == 1) //找到截止频率了{Measure_data.fre_stop = DDS_reg.fre_num;//上限频率measure_sta = MEASURE_NONE_STA; //停止测量Measure_data.data_reg.Measure = 0;//测试停止//这里需要将里面的缓存里的数据显示出XY图fptx_bmp_sta = fptx_rand%3;NORMAL_STATE();//正常状态Measure_data.data_reg.Fptx_sta = 1;DDS_reg.fre_num = 1000;ad9850_wr_serial(0x00,DDS_reg.fre_num);//1K 默认输出max_av = 0;}else //没找到{if(DDS_reg.fre_num < 30000)//30k以下DDS_reg.fre_num += 1000;if(DDS_reg.fre_num >= 30000)//30k以上DDS_reg.fre_num = DDS_reg.fre_num*103/100;//3%ad9850_wr_serial(0x00,DDS_reg.fre_num);//改变频率输出delay_ms(10);DMA_Cmd(DMA2_Channel5,ENABLE);//使能}}else //判断模式{if(Judge_5K_Av_Sta == 0)//5K增益没测{if(FPTX_Cal_5K_Handle() == 0){Judge_5K_Av_Sta = 1;DDS_reg.fre_num = 200000; //200kad9850_wr_serial(0x00,DDS_reg.fre_num);//改变频率输出delay_ms(50);DMA_Cmd(DMA2_Channel5,ENABLE);//使能}}else{if(DDS_reg.fre_num == 200000){if(Judge_Change() == 0){cal_res = FPTX_Cal_200K_Handle();if(cal_res == 0) //C3开路{//C3开路Judge_Change_Mark.Judge_type = C3_OPEN;Judge_Change_Mark.Jude_sta = 1;}else if(cal_res == 2) //C3to2{Judge_Change_Mark.Judge_type = C3_TO_2;Judge_Change_Mark.Jude_sta = 1;}else //C1to2 C2To2 或者无故障{TIM_Cmd(TIM2,DISABLE);//失能定时器2TIM_SetAutoreload(TIM2,1250);//6.4K 200Hz32个点的均方根TIM_SetCounter(TIM2,0);DDS_reg.fre_num = 200; //200Hzad9850_wr_serial(0x00,DDS_reg.fre_num);//改变频率输出delay_ms(100);TIM_Cmd(TIM2,ENABLE);//使能定时器2}}}else if(DDS_reg.fre_num == 200){cal_res = Av_Cal_200Hz_Handle();if(cal_res == 0){Judge_Change_Mark.Judge_type = C2_TO_2;Judge_Change_Mark.Jude_sta = 1;}if(cal_res != 2)measure_sta = MEASURE_NONE_STA;}}if((Judge_Change_Mark.Jude_sta == 1) || (measure_sta == MEASURE_NONE_STA))//找到故障或者幅频测试完毕{TIM_Cmd(TIM2,DISABLE);//失能定时器2TIM_SetAutoreload(TIM2,250);//32K 1KHz32个点的均方根TIM_SetCounter(TIM2,0);TIM_Cmd(TIM2,ENABLE);//使能定时器2Judge_Change_Mark.Judge_Over = 1;//循环一次DC_OFFSET_MEASURE();//测直流偏置vTaskDelay(50);DDS_reg.fre_num = 1000; //1000DDS_reg.fre_sta = 1; //改变频率measure_sta = MEASURE_DC_STA; //测量直流偏置 //循环memset(&Measure_200HzAv_Jun,0,sizeof(Measure_200HzAv_Jun));//清缓存}}break;}}Check_Cal_Data();//校准时的测量}
}

measure_task任务是本程序的重点,这个任务中进行各个量的测量,采用状态机的方式实现,通过判断状态标志得知当前测量的是哪个量,然后进入到对应的计算函数中进行计算。
       序中测量模式下的测量顺序分别为直流量、输入电阻、输出电阻、1kHz下的增益Av、截止频率。由于我使用的显示屏为OLED12864,没办法显示详细的幅频特性曲线,而且评分标准中主要要求测量截止频率,所以程序中并未测量实际的幅频特性曲线,只是测量完成之后会随机显示一幅事先准备好的幅频特性曲线图片。测量完成所有量之后,程序将状态标志设置为MEASURE_NONE_STA停止测量,然后显示测量值。
       断模式下,程序中的测量顺序基本和测量模式下一样,只不过在幅频特性测量环节会有所差异,并且判断模式下程序不会主动停止测量,会进行循环测量,当测量的到的数据异常时,程序会根据异常显示出具体是什么故障。切换到测量模式后,程序才会停止循环测量。
       个任务之后还会进行具体分析,这里只做简单的介绍。

五、ADC配置及数据采集说明

void MY_ADC_Init(void)
{ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC3,ENABLE);//开启ADC1 ADC3的时钟RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14MADC_IO_Init();ADC_DeInit(ADC1);  //复位ADC1ADC_DeInit(ADC3);  //复位ADC3 ADC_DeInit需要放置在所有ADC初始化配置之前 不然会造成数据错乱 配置错误ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;    //ADC工作模式:ADC1和ADC2工作在独立模式ADC_InitStructure.ADC_ScanConvMode = ENABLE; //模数转换工作在多通道模式ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;   //模数转换工作在多次转换模式ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐ADC_InitStructure.ADC_NbrOfChannel = ADC1_CHANNL_NUM;    //顺序进行规则转换的ADC通道的数目ADC_Init(ADC1, &ADC_InitStructure);  //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   #if (PCB_TYPE == 1)ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_7Cycles5 );   //测量放大器输入信号  PC0->UI_ADCADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_7Cycles5 ); //测量放大器输出直流  PC1->UO_DCADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_7Cycles5 );  //测量放大器输出信号  PC2->UO_1ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_7Cycles5 );   //测量放大器输出信号  PC3->UO_2 均方根#endif#if (PCB_TYPE == 2)#endif#if (PCB_TYPE == 3)#endif/******************** ADC1 *****************/ADC_DMACmd(ADC1,ENABLE);//开启ADC1的DMAADC_Cmd(ADC1, ENABLE);    //使能指定ADC1ADC_ResetCalibration(ADC1);   //使能复位校准  while(ADC_GetResetCalibrationStatus(ADC1));   //等待复位校准结束ADC_StartCalibration(ADC1);    //开启AD校准while(ADC_GetCalibrationStatus(ADC1));  //等待校准结束ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件开启ADC1转换ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  //ADC工作模式:独立模式ADC_InitStructure.ADC_ScanConvMode = DISABLE ;   //模数转换工作在单通道模式ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;   //模数转换工作在多次转换模式ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐ADC_InitStructure.ADC_NbrOfChannel = 1;  //顺序进行规则转换的ADC通道的数目ADC_Init(ADC3, &ADC_InitStructure);  //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器 ADC_RegularChannelConfig(ADC3, ADC_Channel_0, 1, ADC_SampleTime_1Cycles5 );   //测量放大器输出信号  PA0->UO_2 扫描/******************** ADC3 *****************/ADC_DMACmd(ADC3,ENABLE);//开启ADC3的DMAADC_Cmd(ADC3, ENABLE); //使能指定ADC3ADC_ResetCalibration(ADC3);   //使能复位校准  while(ADC_GetResetCalibrationStatus(ADC3));   //等待复位校准结束ADC_StartCalibration(ADC3);    //开启AD校准while(ADC_GetCalibrationStatus(ADC3));  //等待校准结束ADC_SoftwareStartConvCmd(ADC3,ENABLE);//软件开启ADC3转换ADC_DMA_Init();
}

序中一共需要测量5路信号,其中ADC1测量4路信号,ADC3测量1路信号,两个ADC都工作在独立模式下。
       ADC1配置为多通道、多次转换、数据右对齐、软件触发转换,调用ADC_RegularChannelConfig函数配置4个通道。然后开启ADC1的DMA,配置为循环模式,16位数据,传输量为4,不开启中断,这样配置后缓存数组的的4个值依次就是ADC_RegularChannelConfig函数配置的通道顺序,所对应的AD转换值最新值。使用TIM2中断进行数据采样,中断中只需要读取缓存数组中的对应元素值即可,TIM2工作在32k的频率下,1k的信号可以采集32个点做均方根计算。——定时器触发ADC采样
       ADC3配置为单通道、多次转换、数据右对齐、软件触发转换,调用ADC_RegularChannelConfig函数配置1个通道,ADC3_Channel_0上的信号和ADC1_Channel_12的信号是相同的,都是Uo_1信号,ADC1_Channel_12只在信号频率不超过1k时进行均方根计算时使用。ADC3_Channel_0通道则是进行扫描法,专门用来测量截止频率的,信号频率大于1k时使用。由于ADC3_Channel_0完成单次转换需要(12.5+1.5)/12M=1.167us,所以要保证1kHz下的信号可以完成一个周期的测量,DMA的传输数据量必须大于(1000/1.167=857)。最后ADC3的DMA配置为单次模式,传输量设置为2000,开启传输完成中断。
       200k频率下周期为5us,5us和76us\frac{7}{6}us67​us的最小公倍数为35us,也就是转换30次即可得到一组最值,所以2000次的转换中可以得到多组波形信号的最值,将最值做差即可得到信号的峰峰值。——高频信号测量原理

篇博客对程序流程等进行了整体分析,之后的博客会对程序进行更为具体细致的分析,主要是测量、判断和校准部分的分析。

PS:程序源码和硬件电路图都在之前发的这个系列博文第一篇中,大家可以在那篇博文的最下面,点击网盘链接进行下载。

2019年TI杯 简易电路特性测试仪 制作过程(4)——程序总体分析 20/04/20相关推荐

  1. 2019年TI杯 简易电路特性测试仪 制作过程(9)——实际测试效果 20/05/24

    经过一个多月的时间,关于简易电路特性测试仪的制作过程系列博客终于迎来的尾声,现在就我自己制作的测试仪来根据测评表来实际测试一下,看看是否能够达到题目的要求. 图1 测评表 一.基础测量部分 1. 标准 ...

  2. 2019年TI杯 简易电路特性测试仪 制作过程(2)——测量电路硬件设计 20/05/17

    一.信号衰减输出部分设计 1.1增益测量时输入信号峰峰值选择 通过计算待测的共射放大电路在1kHz频率下的增益大约在100以上,这个增益会根据不同的管子呈现出细微的不同,我手头搭建的电路经过测试发现此 ...

  3. 2019年TI杯 简易电路特性测试仪 制作过程(6)——测量任务分析(Av、fH) 20/05/01

    一.增益Av测量 1.增益Av测量--采样 uint8_t AV_Sample_1KHz_Handle(void) {uint8_t res = 0;if(Measure_Av_Jun.Uo_ave_ ...

  4. 2019年TI杯 简易电路特性测试仪 制作过程(3)——MCU外围电路、电源电路及接线说明 20/04/18

    一.MCU外围电路说明 需要在原来设计的STM32F103RCT6核心板的基础上制作一块带有按键.显示接口(有的需要)和AD9850模块接口的底板.由于校准参数输入是采用的菜单结构,因此设计了6个按键 ...

  5. 简易电路特性测试仪(2019年国赛D题,该方案全功能实现)

    目录 前言 一.硬件方案 二.作品图 三.评分表 四.基本要求 1.测量输入电阻.输出电阻.绘制幅频特性曲线.显示上限截止频率 2.断开B级,输入电阻在10K-12.2K之间 3.断开B级再断开R2, ...

  6. 2019年全国大学生电子设计大学(D 题)简易电路特性测试仪(1)整题思路方案分析

    2019年全国大学生电子设计大学(D 题)简易电路特性测试仪,此题是特别经典的一道题,对于不选控制类题目的同学,这个题非要有必要训练一下,这个题综合性比起2021年E题收发器难度会差一些,但是还是很考 ...

  7. 2019年电赛国赛D题《简易电路特性测试仪》训练总结----待测三极管共射放大电路部分

    系列文章链接目录 一.2017年电赛国赛H题<远程幅频特性测试装置>训练总结(DDS信号源部分) 二.2017年电赛国赛H题<远程幅频特性测试装置>训练总结(放大器部分) 三. ...

  8. 2019年全国电子设计大赛D题《简易电路特性测试仪》(一)仿真阶段

    文章目录 前言 一.仿真阶段 二.仿真结果 三.仿真结果分析 四.实物制作 总结 前言 国赛就是把往年的真题都做会了,你就会了.这次我们训练的是2019年全国电子设计大赛D题<简易电路特性测试仪 ...

  9. 2019年电赛国赛D题《简易电路特性测试仪》训练总结----题目引入与概述

    系列文章链接目录 一.2017年电赛国赛H题<远程幅频特性测试装置>训练总结(DDS信号源部分) 二.2017年电赛国赛H题<远程幅频特性测试装置>训练总结(放大器部分) 三. ...

最新文章

  1. mysql display size_mysql integer size 大小
  2. 使用 Visual Studio 2019 批量添加代码文件头
  3. iOS统计项目的代码总行数
  4. 46 FI配置-财务会计-固定资产-一般评估-指定平行货币的使用
  5. 流行的编程语言,Audiophile Linux发行版,GNU,Bash,Raspberry PI,DevOps,GIMP等
  6. 《管理3.0》读书笔记
  7. 线性回归 - LinearRegression - 预测糖尿病 - 量化预测的质量
  8. 企业微信检测僵尸粉小工具,企业微信如何检测僵尸粉
  9. 18650锂电池充电方案及保护板电路构思
  10. antlr ques
  11. android常用地图坐标转换
  12. appium+python 自动化测试:解决安卓系统双击问题——获取微信聊天内容
  13. linux给变量加单引号,grep中加单引号与不加引号的区别
  14. 【UVA 815 --- Flooded!】
  15. GTD时间管理简洁做法
  16. Creator新手引导 | 限制只能点击一个按钮 | 文字打字机效果
  17. Java Http 请求方式汇总
  18. mysql 外键有啥用途_外键
  19. 武装我的“超强小黑”Thinkpad T400
  20. stick和stuck的区别_Stick to和Stick with的区别

热门文章

  1. 机器学习基础学习笔记【二】
  2. Hugo 博客搭建教程
  3. python——操作剪贴板,删除文本中的空格
  4. starGAN复现及遇到问题
  5. Wechaty Plugin|实现一个微信机器人几行代码即可
  6. 2017年蓝桥杯C组真题及解析
  7. uniapp/微信获取用户定位
  8. 记错本----git上传项目couldn‘t find remote ref master
  9. Keil5安装包括C51版本和STM32的mdk514版本
  10. 如何在dw上编写php_怎么在dw打开php项目