利用STM32的DAC+TIME产生可调频调幅正弦波

2023-10-07 13:30

本文主要是介绍利用STM32的DAC+TIME产生可调频调幅正弦波,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、如何产生正弦波?
  • 二、生成采样数值函数
    • 1.函数生成DAC数组函数
    • 2.通过高级定时器TIM1更新中断控制DAC输出
  • 三、通过四个按钮控制输出的频率和幅度
  • 四、下面是我的实测波形,附上程序百度网盘
  • 总结


前言

        这个程序非常简单,说白了就是每隔一段时间改变引脚输出的电压,就能得到一个正弦波。

主要是为了方便大家调试FFT,有一个输入大于0小于3.3V取样信号,方便大家学习。

一、如何产生正弦波?

  本文采用查表法的方式生成一个数值范围为[0,4096]的正弦波数组,通过定时器更新中断不断以DAC进行输出,从而产生一个正弦波,并且通过改变定时器的预装载值(ARR)或者预分频系数(psc),改变进入中断的时间进而改变正弦波频率。

二、生成采样数值函数

代码如下:

void out_sine(void) 
{double index = 250;//250个数据float pi = 3.141592;int fori = 0;float outv = 0;for(;fori <index;fori++){outv = 0.5*(sin((2*pi)/index*fori)+1)*4095;printf("%.0f,\t",outv);if(!((fori+1)%8))printf("\r\n");//将数据打印出来}    
}

下表是通过串口软件打印出来的数据,有了这个一维数组我们只需要将数组里的值依次赋给DAC就能得到正弦波啦。

const u16 Sine12bit_250[250] = {
2048,	2099,	2150,	2202,	2253,	2304,	2355,	2406,	
2456,	2507,	2557,	2606,	2656,	2705,	2753,	2801,	
2849,	2896,	2942,	2988,	3034,	3079,	3123,	3166,	
3209,	3251,	3292,	3333,	3372,	3411,	3449,	3486,	
3522,	3558,	3592,	3625,	3657,	3689,	3719,	3748,	
3776,	3803,	3829,	3854,	3878,	3900,	3921,	3942,	
3961,	3978,	3995,	4010,	4024,	4037,	4048,	4059,	
4068,	4075,	4082,	4087,	4091,	4094,	4095,	4095,	
4094,	4091,	4087,	4082,	4075,	4068,	4059,	4048,	
4037,	4024,	4010,	3995,	3978,	3961,	3942,	3921,	
3900,	3878,	3854,	3829,	3803,	3776,	3748,	3719,	
3689,	3657,	3625,	3592,	3558,	3522,	3486,	3449,	
3411,	3372,	3333,	3292,	3251,	3209,	3166,	3123,	
3079,	3034,	2988,	2942,	2896,	2849,	2801,	2753,	
2705,	2656,	2606,	2557,	2507,	2456,	2406,	2355,	
2304,	2253,	2202,	2150,	2099,	2048,	1996,	1945,	
1893,	1842,	1791,	1740,	1689,	1639,	1588,	1538,	
1489,	1439,	1390,	1342,	1294,	1246,	1199,	1153,	
1107,	1061,	1016,	972,	929,	886,	844,	803,	
762,	723,	684,	646,	609,	573,	537,	503,	
470,	438,	406,	376,	347,	319,	292,	266,	
241,	217,	195,   	174,	153,	134,	117,	100,	
85,	    71,	    58,	    47,	    36,	    27,	    20,	    13,	
8,	    4,	    1,	    0,	    0,	    1,	    4,	    8,	
13,	    20,	    27,	    36,	    47,	    58,	    71,	    85,	
100,	117,	134,	153,	174,	195,	217,	241,	
266,	292,	319,	347,	376,	406,	438,	470,	
503,	537,	573,	609,	646,	684,	723,	762,	
803,	844,	886,	929,	972,	1016,	1061,	1107,	
1153,	1199,	1246,	1294,	1342,	1390,	1439,	1489,	
1538,	1588,	1639,	1689,	1740,	1791,	1842,	1893,	
1945,	1996,};

2.通过高级定时器TIM1更新中断控制DAC输出

代码如下:

#define CLIP_ROT(V,MIN,MAX) ( ( V>MAX?MIN:(V<MIN?MAX:V) ) )  
void AdcPushData()
{static int DAC_index_1 = 0;DAC_SetChannel1Data(DAC_Align_12b_R,(Sine12bit_250[DAC_index_1])*DacAmp/10);//250个点        4Khz(0.4ms)DAC_index_1++;DAC_index_1 = CLIP_ROT(DAC_index_1,0,250);
}void Timer1_Init(u16 arr,u16 psc)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrecture;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);/*使能定时器1的时钟*/NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn;/*定时器1的中断通道使能*/NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;/*定时器1的中断通道使能*/NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;/*抢占优先级*/NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;/*响应优先级*/NVIC_Init(&NVIC_InitStructure);/*配置中断分组,并使能中断*/TIM_TimeBaseInitStrecture.TIM_Period = arr;/*重装载寄存器*/TIM_TimeBaseInitStrecture.TIM_Prescaler = psc;/*预分配*/TIM_TimeBaseInitStrecture.TIM_ClockDivision = TIM_CKD_DIV1;/*时钟分频*/TIM_TimeBaseInitStrecture.TIM_CounterMode = TIM_CounterMode_Up;/*向上计数*/TIM_TimeBaseInitStrecture.TIM_RepetitionCounter = 0;/*重复计数寄存器*/TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStrecture);/*初始化*/TIM_ClearFlag(TIM1,TIM_FLAG_Update);/*清更新标志位*/TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);/*使能中断*/TIM_Cmd(TIM1,ENABLE);/*使能计数*/}void TIM1_UP_TIM10_IRQHandler(void)
{if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET){//判断TIM中断发生与否:TIM 中断源 TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除中断标志位,否则卡死在中断里 
/***************在此处添加中断执行内容******************/AdcPushData();LED1 = ~LED1;}
}

中断配置好了就可以输出一个好看的正弦波了,那怎么调频和调幅呢?

二、通过四个按钮控制输出的频率和幅度

代码如下:

static int DacAmp = 0.0;void Sine()
{u16 key=KEY_Scan(0);static u16 F = 128 - 1 ;//默认50HZ	switch(key){case WKUP_PRES:DacAmp +=1;break;//case KEY1_PRES:DacAmp -=1;break;case KEY2_PRES:F += 10;break;//改变TIM1的预装载值,从而改变频率case KEY0_PRES:F -= 10;break;default:break;}DacAmp = CLIP_ROT(DacAmp,0,10);TIM1->ARR = F;// 改变预分配系数也是可行的,(PSC)TIM1->PSC =F;}

按下WKUP_PRES和KEY1_PRES,正弦波幅值变化,KEY2_PRES和KEY0_PRES控制频率变化。

三、下面是我的实测波形

 附上代码:链接:https://pan.baidu.com/s/1aXAH2Qu5vF8uVKZdXpQx0g?pwd=1234 
提取码:1234

需要的自取哈,代码写的不好,就当交流学习。

总结

额,不知道写啥,有问题请留言,如果觉得有用的话,请点个赞,不胜感激。

这篇关于利用STM32的DAC+TIME产生可调频调幅正弦波的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/158068

相关文章

MySQL中时区参数time_zone解读

《MySQL中时区参数time_zone解读》MySQL时区参数time_zone用于控制系统函数和字段的DEFAULTCURRENT_TIMESTAMP属性,修改时区可能会影响timestamp类型... 目录前言1.时区参数影响2.如何设置3.字段类型选择总结前言mysql 时区参数 time_zon

Python 标准库time时间的访问和转换问题小结

《Python标准库time时间的访问和转换问题小结》time模块为Python提供了处理时间和日期的多种功能,适用于多种与时间相关的场景,包括获取当前时间、格式化时间、暂停程序执行、计算程序运行时... 目录模块介绍使用场景主要类主要函数 - time()- sleep()- localtime()- g

如何使用 Bash 脚本中的time命令来统计命令执行时间(中英双语)

《如何使用Bash脚本中的time命令来统计命令执行时间(中英双语)》本文介绍了如何在Bash脚本中使用`time`命令来测量命令执行时间,包括`real`、`user`和`sys`三个时间指标,... 使用 Bash 脚本中的 time 命令来统计命令执行时间在日常的开发和运维过程中,性能监控和优化是不

MCU7.keil中build产生的hex文件解读

1.hex文件大致解读 闲来无事,查看了MCU6.用keil新建项目的hex文件 用FlexHex打开 给我的第一印象是:经过软件的解释之后,发现这些数据排列地十分整齐 :02000F0080FE71:03000000020003F8:0C000300787FE4F6D8FD75810702000F3D:00000001FF 把解释后的数据当作十六进制来观察 1.每一行数据

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

STM32内部闪存FLASH(内部ROM)、IAP

1 FLASH简介  1 利用程序存储器的剩余空间来保存掉电不丢失的用户数据 2 通过在程序中编程(IAP)实现程序的自我更新 (OTA) 3在线编程(ICP把整个程序都更新掉) 1 系统的Bootloader写死了,只能用串口下载到指定的位置,启动方式也不方便需要配置BOOT引脚触发启动  4 IAP(自己写的Bootloader,实现程序升级) 1 比如蓝牙转串口,

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类

linux 下Time_wait过多问题解决

转自:http://blog.csdn.net/jaylong35/article/details/6605077 问题起因: 自己开发了一个服务器和客户端,通过短连接的方式来进行通讯,由于过于频繁的创建连接,导致系统连接数量被占用,不能及时释放。看了一下18888,当时吓到了。 现象: 1、外部机器不能正常连接SSH 2、内向外不能够正常的ping通过,域名也不能正常解析。