三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

微信网站有什么作用做ps可以在哪些网站上找素材

微信网站有什么作用做ps可以在哪些网站上找素材 微信网站有什么作用,做ps可以在哪些网站上找素材,平面设计资源网站,网站 建设 步骤stm32调制解调2fsk信号 调制 配置 DAC 使用DAC+TIM+DMA控制,打开DAC的通道,并选择使用TIM2触发,DMA打开Circular模式(h7配置)DMA配置同上:打开Circular模式,选择Half World 定时器(需要开启中断) 配置定时器2,… stm32调制解调2fsk信号 调制 配置 DAC 使用DAC+TIM+DMA控制,打开DAC的通道,并选择使用TIM2触发,DMA打开Circular模式(h7配置)DMA配置同上:打开Circular模式,选择Half World 定时器(需要开启中断) 配置定时器2,打开时钟源配置PSC为1-1,ARR任意(不要太大,否则第一次进入中断会很慢),后续将在代码中修改,auto-reload preload为enable,防止修改ARR时定时器卡住,最后务必打开Updata Event,否则DAC无法使用TIM2,打开TIM2的中断:打开TIM7,设置为6ms中断,用来输出码元(即一个码元持续6ms)打开TIM7的中断:参考代码 uint8_t send[12] = {1,1,1,0,1,0,1,0,1,1,1,0}; uint8_t signal; //存储二进制数 uint8_t num1; void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {if(htim==htim2){if(signal == 1)TIM2-ARR = 2000 - 1; //修改正弦波频率为1000HzelseTIM2-ARR = 4000 - 1; //修改正弦波频率为500Hz}if(htim == htim7) //6ms{// printf("222\r\n");signal = send[num1]; //将数组赋值给signanum1++; if(num1 = 12) num1 = 0; //加上包头包尾和数据共有12个码元 } }uint16_t sinx[120]; for (int i = 0; i 120; i++) {sinx[i] =(sin(i * 2 * 3.14159265358 / 120) + 1.2) * 1700; } HAL_TIM_Base_Start_IT(htim2); HAL_TIM_Base_Start_IT(htim7); // TIM2-ARR = 2000 - 1; HAL_DAC_Start_DMA(hdac1,DAC_CHANNEL_1,(uint32_t *)sinx,120,DAC_ALIGN_12B_R);解调 配置 ADC 打开相应的ADC,使用ADC+TIM+DMA控制,打开ADC的通道,并选择使用TIM3触发,DMA打开Normal模式(h7配置)定时器 配置定时器3,打开时钟源配置PSC为84-1,ARR为100-1(此时的采样频率为10Khz),最后务必打开Updata Event,否则ADC无法使用TIM3参考代码 uint16_t adc_buff[2048];//存放ADC采集的数据 // FIR 滤波器相关全局数组 uint16_t BL = 46; float32_t TB[46] = { -0.00192302686307542, -0.00179186182294684, -0.000828174329093916,0.00104096891537065, 0.00357678176218631, 0.00619782240763762,0.00805660256598988, 0.00822795688466835, 0.00597902573319143,0.00105907891428945, -0.00607131593929422, -0.0141504401553351,-0.0212186454280924, -0.0249244480145768, -0.0229903049074396,-0.0137466035336783, 0.00338734878600169, 0.0275978052390779,0.0566387991445388, 0.0870980799701347, 0.114933113960468,0.136177607324765, 0.147673829385213, 0.147673829385213,0.136177607324765, 0.114933113960468, 0.0870980799701347,0.0566387991445388, 0.0275978052390779, 0.00338734878600169,-0.0137466035336783, -0.0229903049074396, -0.0249244480145768,-0.0212186454280924, -0.0141504401553351, -0.00607131593929422,0.00105907891428945, 0.00597902573319143, 0.00822795688466835,0.00805660256598988, 0.00619782240763762, 0.00357678176218631,0.00104096891537065, -0.000828174329093916, -0.00179186182294684,-0.00192302686307542 }; uint32_t blockSize = 2048; float32_t pState[2093] = {0.0f}; float fir_inputbuf[2048] = {0}; float fir_outputbuf[2048] = {0}; arm_fir_instance_f32 S; #define V_MAX 21 //用10Khz采样频率去采500Hz波一个周期有20个点 故设置为20+1 uint8_t v = 0; uint16_t high_time,low_time; uint8_t flag,high_count,low_count,num; uint8_t recieve[35]; #define SAMPLING_FREQ_HZ 10000 // ADC采样频率(Hz),当前为10kHz #define SYMBOL_PERIOD_MS 6 // 每个码元的时间宽度(ms),当前为6ms #define SAMPLES_PER_SYMBOL ((SAMPLING_FREQ_HZ * SYMBOL_PERIOD_MS) / 1000) // 每码元采样点数(=60) #define HALF_SAMPLES (SAMPLES_PER_SYMBOL / 2) // 用于四舍五入(=30) void decode_demodulated_data(void) {// ============ 第一步:计算直流偏置(均值) ============float dc_offset = 0.0f;for(uint16_t i=0; i2048; i++){dc_offset += fir_outputbuf[i];}dc_offset /= 2048.0f; // 得到平均值作为直流偏置// ============ 第二步:绝对值处理(自适应) ============// 原理:将低于直流偏置的部分翻转(镜像),再减去直流偏置,得到以0为中心的正信号for(uint16_t i=0; i2048; i++){if(fir_outputbuf[i] dc_offset)fir_outputbuf[i] = 2.0f * dc_offset - fir_outputbuf[i]; // 相当于 峰峰值 - 原值fir_outputbuf[i] -= dc_offset; // 去除直流,使信号围绕0对称}// ============ 第三步:模拟电容充放电判决(包络检波) ============// 注意:此时信号已经是以0为中心的正幅度,但最高幅度可能不固定,需根据实际信号调整阈值// 原来的阈值 0.8 和 V_MAX/4 是基于固定幅度设计的,自适应后阈值也应动态调整。// 一种简单方法:计算当前信号的最大值,按比例设定阈值。float max_val = 0.0f;for(uint16_t i=0; i2048; i++){if(fir_outputbuf[i] max_val) max_val = fir_outputbuf[i];}// 防止最大值为0的情况if(max_val 0.001f) max_val = 0.001f;float charge_threshold = 0.5f * max_val; // 充电阈值(原0.8对应最大值的50%左右)float decision_threshold = 0.25f * max_val; // 判决阈值(原V_MAX/4对应最大值的25%)for(uint16_t i=0; i2048; i++){if (fir_outputbuf[i] charge_threshold) // 当前值大于充电阈值v = V_MAX; // 模拟电容快速充电else{if(v 0) v--; else v = 0; // 放电}if (v decision_threshold) // 电压大于判决阈值fir_outputbuf[i] = 1.0f; // 输出逻辑1elsefir_outputbuf[i] = 0.0f; // 输出逻辑0}// ============ 第四步:根据电平时间解调码元 ============// 6ms一个码元,10Khz采样率 所以每60个点一个码元high_time = 0;low_time = 0;flag = 0;high_count = 0;low_count = 0;num = 0;for(uint16_t i=0; i2048; i++){if(fir_outputbuf[i] == 1){high_time++; if(flag == 0) //遇到电平翻转(低→高){low_count = low_time / SAMPLES_PER_SYMBOL; // 6ms一个码元,10Khz采样率 所以每60个点一个码元if(low_time % SAMPLES_PER_SYMBOL = HALF_SAMPLES) low_count++; //四舍五入low_time = 0;for(int j=0; jlow_count; j++){recieve[num] = 1; //赋入recieve数组num++;} low_count = 0;}flag = 1; //高电平的标准}else{low_time++;if(flag == 1) //遇到电平翻转(高→低){ high_count = high_time / SAMPLES_PER_SYMBOL;if(high_time % SAMPLES_PER_SYMBOL = HALF_SAMPLES) high_count++;high_time = 0;for(int j=0; jhigh_count; j++){recieve[num] = 0;num++;} high_count = 0; } flag = 0; }} }// 打开ADC并延时200ms(6ms一个码元,一个周期有12个码元,所以两个周期一个要144ms才能采完)保证能够采集完毕,之后关闭ADC进行数据处理 HAL_TIM_Base_Start(htim3); HAL_ADC_Start_DMA(hadc1,(uint32_t *)adc_buff,2048); HAL_Delay(200); HAL_ADC_Stop_DMA(hadc1); // for(uint16_t i = 0; i 2048; i++) // { // printf("%.3f\n",adc_buff[i]*3.3/4096); // } // FIR 滤波处理(所有数组已在全局定义)不一定需要 arm_fir_init_f32(S, BL, TB, pState, blockSize);for (uint16_t i = 0; i 2048; i++) {fir_inputbuf[i] = (float)adc_buff[i] * 3.3f / 4096.0f; }arm_fir_f32(S, fir_inputbuf, fir_outputbuf, blockSize);// for (uint16_t i = 0; i 2048; i++) { // printf("%.3f,%.3f\n", fir_inputbuf[i], fir_outputbuf[i]); // } decode_demodulated_data(); // ========== 打印解调结果 ========== printf("Decoded bits (%d bits): ", num); for (uint16_t i = 0; i num; i++) {printf("%d", recieve[i]); } printf("\r\n");
← 返回列表