当前位置:   article > 正文

2022年电赛F题 信号调制度测量装置

2022年电赛f题

红叶何时落水

 题目要求:

一、任务

设计制作信号调制度测量装置,该装置测量并显示信号源输出的被测信号调制度等参数,识别并显示被测信号的调制方式,输出解调信号。测量系统如图1所示。

二、要求

(1)被测信号为电压峰峰值100mV的普通单音调幅(AM)电压,其载频为10MHz、调制信号为频率1~3kHz的正弦信号。测量并显示的调幅度,要求测量误差绝对值≤0.1;输出解调信号,要求解调信号波形无明显失真。 (20分)

(2)被测信号为电压峰峰值100mV的单音调频(FM)电压,其载频为10MHz、调制信号为频率3~5kHz的正弦信号。测量并显示的调频度,测量误差绝对值≤0.3;测量并显示的最大频偏(kHz);输出解调信号,要求解调信号波形无明显失真。(25分)

(3)被测信号为载波电压峰峰值100mV的高频电压,其载频范围为10MHz~30MHz(频率步进间隔0.5MHz)。若为已调波(AM或FM波)时,其调制信号为频率范围5kHz~10kHz(频率步进间隔1kHz)内某一频率的正弦信号。测量装置应能自主识别的调制方式,即能判断出为调幅、调频或未调载波。测量并显示的调制度(或),测量误差要求分别同前面第 (1) 、(2)项的要求;当被测信号为调频波时,要求测量并显示其最大频偏(kHz);输出解调信号,要求解调信号波形无明显失真。(45分)

任务分析

主要的任务是AM信号与FM信号要实现解调,并且测量出相关参数;

简单来说有两套方案

第一套硬件解调,并将所需测量的参数转化为电压量。由单片机测量参数,进行计算和显示;

AM解调

首先,将信号放大,上拉到2V左右。然后用包络检波电路将其解调出来,再加一个底通滤波器即可。

具体电路见:效果图

                       原理图与连线图

FM解调我没做,好像是用鉴相器制作。

难点:载波频率为10MHZ,普通的芯片频带无法实现。

比如说AM的解调,如果我们打算用820单运放将其放大并上拉,我们就会发现当载波为10Mhz时,输出的信号实现了放大功能。但一旦将载波信号变为20MHZ,增益便会发生变化(频带不够宽)。当然,增益发生变化对于信号的解调影响不大,还是可以解出来的。但是,AM的调幅度是用解调出来的正弦波的峰峰值/直流偏置得来的。因为增益发生变化,会导致参数发生变化。所以后面单片机的测量便有很大的麻烦。(一会在软件部分说明)

解决方案,使用无源电路将其衰减(防止调制波在放大模块那里出现失真),进入专用放大模块,之后,不进行上拉,直接让二极管将上半个调试波形解调出来。这样就避免了820的带宽问题。但是,这个方案需要一直去调阻抗,一不小心,信号直接衰没了。

第二套软件解调并测量

AM 对于周期信号来说,我们可以通过快速FFT运算,从频谱图中分析他的各种谐波。

难点

1.根据奈奎斯特采样定理,我们知道想要分析出频谱不混叠的频谱图,采样率必须大于最大谐波的二倍。那么就意味着AD采样率要大于60Mhz。普通的32单片机明显达不到这个采样率。就拿F103芯片来说,板载AD采样率在正常工作范围内为1Mhz。如果使AD超频工作的化,也只能达到2.5Mhz,与此同时,把主时钟超频到112M,采样率勉强达到4.5M。但此时采集到的波精度已经有了不小的损失。如果外接AD的话,也不太行,经过测试最大采样率为25M。如果用FPGA的话,采样率倒是可以达到60M。

所以,想实现软件解调,就要用带通采样(传送门

这里我采用的是204khz的采样率,刚好可以包含题目中所有的频率。

AM频谱图有三个谐波,最长的那根的频率便是载波频率。而两根短谐波之间的频率差便是调制波信号的频率。

对于FM 同样采样率,会出现多个周期的谐波

 我们可以通过分析该频谱来得出所有信息。

信息采集完毕后,用板载DA输出一个相应频率的正弦波即可。(如果觉得DA输出的波形不够好看,加个滤波电路滤一下即可)。

明天开始测评。

代码部分:

采样率204khzAD配置

TIM1_PWM定时器配置

  1. void tim1_pwm_config(uint16_t psc,uint16_t arr,uint8_t val)
  2. {
  3. RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
  4. TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
  5. TIM_TimeBaseInitStruct.TIM_Period = arr -1;
  6. TIM_TimeBaseInitStruct.TIM_Prescaler = psc -1;
  7. TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
  8. TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);
  9. TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
  10. TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
  11. TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
  12. TIM_OCInitStruct.TIM_Pulse = arr / 2;
  13. TIM_OC1Init(TIM1,&TIM_OCInitStruct);
  14. TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
  15. TIM_CtrlPWMOutputs(TIM1,ENABLE);
  16. TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_OC1);
  17. TIM_Cmd(TIM1,ENABLE);
  18. }

DMA1配置

  1. void Adc_dma(void)
  2. {
  3. //ADC1 DMA1_CHANNEL1
  4. DMA_InitTypeDef DMA_InitStruct;
  5. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
  6. DMA_InitStruct.DMA_BufferSize = size;
  7. DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
  8. DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
  9. DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)ADC_arr;
  10. DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  11. DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
  12. DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
  13. DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR));
  14. DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  15. DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  16. DMA_InitStruct.DMA_Priority = DMA_Priority_High;
  17. DMA_Init(DMA1_Channel1,&DMA_InitStruct);
  18. DMA_Cmd(DMA1_Channel1,ENABLE);
  19. }

ADC1配置

  1. void adc_init(void)
  2. {
  3. int i=0;
  4. ADC_InitTypeDef ADC_InitStruct;
  5. for(i=0; i<size; i++)
  6. {
  7. ADC_arr[i]=0;
  8. }
  9. adc_gpio_init();
  10. Adc_dma();
  11. adc_nvic_init();
  12. RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
  13. ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;
  14. ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
  15. // ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  16. ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
  17. ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
  18. ADC_InitStruct.ADC_NbrOfChannel = 1;
  19. ADC_InitStruct.ADC_ScanConvMode = DISABLE;
  20. ADC_Init(ADC1,&ADC_InitStruct);
  21. // ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);
  22. RCC_ADCCLKConfig(RCC_PCLK2_Div6);
  23. ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_1Cycles5);
  24. ADC_DMACmd(ADC1,ENABLE);
  25. ADC_ExternalTrigConvCmd(ADC1, ENABLE);
  26. ADC_Cmd(ADC1,ENABLE);
  27. ADC_ResetCalibration(ADC1);
  28. while(ADC_GetResetCalibrationStatus(ADC1) == SET);
  29. ADC_StartCalibration(ADC1);
  30. while(ADC_GetCalibrationStatus(ADC1) == SET);
  31. }

FFT计算函数

  1. typedef double real;
  2. typedef struct{
  3. real Re;
  4. real Im;
  5. } complex;
  6. double arr_res[_N] = {0};
  7. void fft( complex *v, int n, complex *tmp )
  8. {
  9. if(n>1) { /* N???1,????*/
  10. int k,m; complex z, w, *vo, *ve;
  11. ve = tmp; vo = tmp+n/2;
  12. for(k=0; k<n/2; k++) {
  13. ve[k] = v[2*k];
  14. vo[k] = v[2*k+1];
  15. }
  16. fft( ve, n/2, v ); /* FFT ???? v[] */
  17. fft( vo, n/2, v ); /* FFT ???? v[] */
  18. for(m=0; m<n/2; m++) {
  19. w.Re = cos(2*PI*m/(double)n);
  20. w.Im = -sin(2*PI*m/(double)n);
  21. z.Re = w.Re*vo[m].Re - w.Im*vo[m].Im; /* Re(w*vo[m]) */
  22. z.Im = w.Re*vo[m].Im + w.Im*vo[m].Re; /* Im(w*vo[m]) */
  23. v[ m ].Re = ve[m].Re + z.Re;
  24. v[ m ].Im = ve[m].Im + z.Im;
  25. v[m+n/2].Re = ve[m].Re - z.Re;
  26. v[m+n/2].Im = ve[m].Im - z.Im;
  27. }
  28. }
  29. return;
  30. }
  31. void ifft( complex *v, int n, complex *tmp )
  32. {
  33. if(n>1) {
  34. int k,m; complex z, w, *vo, *ve;
  35. ve = tmp; vo = tmp+n/2;
  36. for(k=0; k<n/2; k++) {
  37. ve[k] = v[2*k];
  38. vo[k] = v[2*k+1];
  39. }
  40. ifft( ve, n/2, v ); /* FFT ???? v[] */
  41. ifft( vo, n/2, v ); /* FFT ???? v[] */
  42. for(m=0; m<n/2; m++) {
  43. w.Re = cos(2*PI*m/(double)n);
  44. w.Im = sin(2*PI*m/(double)n);
  45. z.Re = w.Re*vo[m].Re - w.Im*vo[m].Im; /* Re(w*vo[m]) */
  46. z.Im = w.Re*vo[m].Im + w.Im*vo[m].Re; /* Im(w*vo[m]) */
  47. v[ m ].Re = ve[m].Re + z.Re;
  48. v[ m ].Im = ve[m].Im + z.Im;
  49. v[m+n/2].Re = ve[m].Re - z.Re;
  50. v[m+n/2].Im = ve[m].Im - z.Im;
  51. }
  52. }
  53. return;
  54. }
  55. void fft_dispose(float arr[]) {
  56. complex v[_N], scratch[_N];
  57. double amp[_N];
  58. int k, i;
  59. printf("in");
  60. for(k=0; k<_N; k++) {
  61. v[k].Re = arr[k];
  62. v[k].Im = 0;
  63. }
  64. fft(v, _N, scratch );
  65. printf("\n\r\n\r\n\r");
  66. for(i = 1; i < _N/2; i++)
  67. {
  68. arr_res[i] = sqrt(v[i].Re*v[i].Re+v[i].Im*v[i].Im);
  69. printf("%f,",arr_res[i]);
  70. }
  71. printf("\n\r\n\r\n\r");
  72. }

DA配置

  1. void Dac2_Init()
  2. {
  3. GPIO_InitTypeDef GPIO_InitStructure;
  4. DAC_InitTypeDef DAC_InitType;
  5. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  6. RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
  7. DAC_DeInit();
  8. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  10. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11. GPIO_Init(GPIOA, &GPIO_InitStructure);
  12. GPIO_SetBits(GPIOA, GPIO_Pin_5);
  13. DAC_StructInit(&DAC_InitType);
  14. DAC_InitType.DAC_Trigger = DAC_Trigger_T4_TRGO;
  15. DAC_InitType.DAC_WaveGeneration = DAC_WaveGeneration_None;
  16. DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
  17. DAC_InitType.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
  18. DAC_Init(DAC_Channel_2, &DAC_InitType);
  19. DAC_Cmd(DAC_Channel_2, ENABLE);
  20. DAC_DMACmd(DAC_Channel_2, ENABLE);
  21. }

DMA2配置

  1. void MYDMA_Config(u32 cpar, u32 cmar, u16 cndtr) // cpar?????,cmar?????,cndtr????????(???????)
  2. {
  3. DMA_InitTypeDef DMA_InitStructure;
  4. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
  5. DMA_DeInit(DMA2_Channel4);
  6. DMA_StructInit(&DMA_InitStructure);
  7. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  8. DMA_InitStructure.DMA_BufferSize = cndtr;
  9. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  10. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  11. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  12. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  13. DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  14. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  15. DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  16. DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;
  17. DMA_InitStructure.DMA_MemoryBaseAddr = cmar;
  18. DMA_Init(DMA2_Channel4, &DMA_InitStructure);
  19. DMA_Cmd(DMA2_Channel4, ENABLE);
  20. }

TIM4配置

  1. void TIM4_Config(u16 arr,u16 psc)
  2. {
  3. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  4. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
  5. TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  6. TIM_TimeBaseStructure.TIM_Period = arr - 1;
  7. TIM_TimeBaseStructure.TIM_Prescaler = psc;
  8. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  9. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  10. TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
  11. TIM_SelectOutputTrigger(TIM4,TIM_TRGOSource_Update);
  12. TIM_Cmd(TIM4, ENABLE);
  13. }

main

  1. int main(void)
  2. {
  3. u16 i;
  4. u16 n = NPT;
  5. int *p;
  6. int *f;
  7. double m;
  8. double v_x = 0,i_x;
  9. int h = 0;
  10. Init();
  11. while(1)
  12. {
  13. delay_s(1);
  14. for(i = 0; i < Votage_BUFFER_Size; i++)
  15. {
  16. XR[i]=ADC_arr[i];
  17. }
  18. qsort(ADC_arr, Votage_BUFFER_Size, sizeof(ADC_arr[0]), compDec);
  19. LCD_ShowxNum(132,300, (u32)(ADC_arr[1900] - ADC_arr[120]) * 1000 / ADC_arr[120],5,16,0X80);
  20. printf("\n\r\n\r");
  21. fft();
  22. for(i = 0; i < Votage_BUFFER_Size ; i++)
  23. {
  24. XI[i] = XR[i];
  25. }
  26. GET_code(XI, XR);
  27. draw(XR, 512, 10);
  28. DMA_DeInit(DMA1_Channel1);
  29. adc_init();
  30. IWDG_Feed();
  31. }
  32. }
  33. void Init(void) {
  34. int i = 0;
  35. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  36. delay_init(); //ÑÓʱº¯Êý³õʼ»¯
  37. uart_init(115200); //´®¿Ú³õʼ»¯Îª9600
  38. LED_Init(); //³õʼ»¯ÓëLEDÁ¬½ÓµÄÓ²¼þ½Ó¿Ú
  39. LCD_Init();
  40. adc_init();
  41. IWDG_Init(4,3125);
  42. i = 1000000 / Fs;
  43. tim1_pwm_config(72, (u16) i,1);
  44. for(i = 0; i < 72; i++) {
  45. SIN[i] = SIN[i] * 5 ;
  46. }
  47. Dac2_Init();
  48. MYDMA_Config( (u32) & (DAC->DHR12R2), (u32)SIN, 72);
  49. //TIM4_Config(100000 / tim4, 0);
  50. }

完整工程如有需要,请到微信小程序“非遗种草社”中留言

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/990857
推荐阅读
相关标签
  

闽ICP备14008679号