STM32-正弦波可调(50HZ~20KHZ可调、峰峰值0~3.3V可调)
1.原理:
通过定时器每隔一段时间触发一次DAC转换,然后通过DMA发送正玄波码表值给DAC.
- 当需要改变频率HZ时,只需要修改定时器频率即可(最高只能达到20KHz)
- 当需要改变正玄波的正峰峰值/负峰峰值时,只需要修改正玄波码表即可
2.实现
代码如下所示(采用的是定时器2,DAC引脚是PA4)
#define HZ(x) (u16)(72000000/sizeof(Sine12bit)*2/x) //计算Hz
#define DAC_DHR12R1 0x40007408 //外设DAC通道1的基地址
u16 Sine12bit[] = { //正弦波描点
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , };
/*************************************************************
Function : set_Sine12bit
Description : 设置正玄波码表
Input : MAX(正峰峰值) MIN(负峰峰值)
return : none
*************************************************************/
void Set_Sine12bit(float MAX,float MIN)
{
int i;
float jiaodu=;
float MID=(MAX+MIN)/2.0; //中间峰值
if(MAX>3.3) MAX=3.3;
else if(MAX<=MIN) MIN=;
for(i=;i<;i++)
{
jiaodu=i*0.0247369; //当i =127时,表示为180度,由于sin()是弧度制,所以需要转换
Sine12bit[i]= ((float)sin(jiaodu)*(MAX-MID)+MID)*1241.212; //1241.212是比例,等于4096/3.3
}
}
/*************************************************************
Function : Set_Period
Description : 设置频率hz
Input : value(需要设置的频率hz值)
return : none
*************************************************************/
void Set_Period(u32 value)
{
TIM_ARRPreloadConfig(TIM2,DISABLE);
TIM2->ARR=HZ(value); //更新预装载值
TIM_ARRPreloadConfig(TIM2,ENABLE);
}
/*************************************************************
Function : TIM2_Int_Init
Description: 初始化定时器2
Input : Hz (需要初始化的频率hz值)
return : none
*************************************************************/
void TIM2_Int_Init(u32 Hz)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//初始化定时器2与6的时钟
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = HZ(Hz); //正弦波频率设置
TIM_TimeBaseStructure.TIM_Prescaler = 0x0; //没有预分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //时钟不分频 72M
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //增计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);//更新TIM2输出触发
}
/*************************************************************
Function : DAC_DMA_Config
Description: 初始化DAC和DMA
Input : none
return : none
*************************************************************/
void DAC_DMA_Config(void)
{
DAC_InitTypeDef DAC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//初始化DAC的时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);//初始化DMA2的时钟
/*初始化GPIO*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 ;//DAC channel1和channel2对应的引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*初始化DAC寄存器*/
DAC_StructInit(&DAC_InitStructure);
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;//指定DAC1的触发定时器TIM2
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;//无波形产生
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; //不是能DAC输出缓冲
DAC_Init(DAC_Channel_1, &DAC_InitStructure);//初始化DAC channel1
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC channel1
DAC_DMACmd(DAC_Channel_1, ENABLE); //使能DAC Channel1的DMA
/*初始化DMA寄存器*/
DMA_DeInit(DMA2_Channel3); //将DMA配置成默认值
DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12R1;//指定DMA2通道3的目标地址为DAC1_DHR12R1
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Sine12bit;//指定DMA的源地址为数组Sine12bit
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//外设作为数据传输的目的地
DMA_InitStructure.DMA_BufferSize = sizeof(Sine12bit)/;//DMA缓冲区大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设机地址存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据宽度为半字
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//内存数据宽度为半字
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//工作在循环缓存模式,数据传输数为0时,自动恢复配置初值
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//非常高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//通道未被设置成内存到内存模式,与循环模式相对
DMA_Init(DMA2_Channel3, &DMA_InitStructure);//初始化DMA
DMA_Cmd(DMA2_Channel3, ENABLE); //使能DMA的channel3
TIM_Cmd(TIM2, ENABLE); //最后开启TIM2转换
}
然后在main()函数里,调用USART_handler()
其中USART_handler()函数实现如下:
void USART_handler()
{
u8 len;
u32 hz; //获取HZ频率
float dac_max,dac_min; //获取DAC峰值 if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x2F;
USART_RX_BUF[len]=;
sscanf((char *)USART_RX_BUF,"%d,%f,%f",&hz,&dac_max,&dac_min);
printf("SET HZ = %d, MAX = %f,MIN = %f\r\n", hz,dac_max,dac_min); Set_Sine12bit(dac_max,dac_min); //更改峰值
Set_Period( hz); //更改频率 USART_RX_STA=;
}
}
3.进入串口试验
1)设置频率=50hz,正峰值=3.3V,负峰值=0V,串口则发送50,3.3,0.0,如下图所示:

示波器测量:

2)设置频率=100hz,正峰值=3V,负峰值=0V, 串口则发送100,3,0.0:

3)设置频率=100hz,正峰值=2V,负峰值=1V, 串口则发送100,2,1:

4)设置频率=1khz,正峰值=3.3V,负峰值=0V, 串口则发送1000,3.3,0:

5)设置频率=20khz,正峰值=3.3V,负峰值=0V,串口则发送20000,3.3,0:

是不是很简单~
STM32-正弦波可调(50HZ~20KHZ可调、峰峰值0~3.3V可调)的更多相关文章
- Cloudera Hadoop 5& Hadoop高阶管理及调优课程(CDH5,Hadoop2.0,HA,安全,管理,调优)
1.课程环境 本课程涉及的技术产品及相关版本: 技术 版本 Linux CentOS 6.5 Java 1.7 Hadoop2.0 2.6.0 Hadoop1.0 1.2.1 Zookeeper 3. ...
- [Spark性能调优] 第一章:性能调优的本质、Spark资源使用原理和调优要点分析
本課主題 大数据性能调优的本质 Spark 性能调优要点分析 Spark 资源使用原理流程 Spark 资源调优最佳实战 Spark 更高性能的算子 引言 我们谈大数据性能调优,到底在谈什么,它的本质 ...
- spark 性能调优(一) 性能调优的本质、spark资源使用原理、调优要点分析
转载:http://www.cnblogs.com/jcchoiling/p/6440709.html 一.大数据性能调优的本质 编程的时候发现一个惊人的规律,软件是不存在的!所有编程高手级别的人无论 ...
- elasticsearch5.3.0 bulk index 性能调优实践
elasticsearch5.3.0 bulk index 性能调优实践 通俗易懂
- JVM的常用的调优策略和垃圾回收算法及Tomcat的常用调优参数
jvm调优主要针对堆内存,堆内存分为:新生区.养老区和永久区 永久区存放的是系统jdk自身的interface和class的元数据,所以唯有新生区和养老区具有优化空间. 新生区:伊甸区和幸存者区.所有 ...
- Nginx-PHP优化设置 + lnmp调优的关键影响因素 + php-fpm + nginx返回码 + tcp调优 + 最大文件描述符
https://www.cnblogs.com/zengkefu/p/5602473.html最大文件描述符 https://blog.csdn.net/fanren224/article/detai ...
- 性能调优的本质、Spark资源使用原理和调优要点分析
本课主题 大数据性能调优的本质 Spark 性能调优要点分析 Spark 资源使用原理流程 Spark 资源调优最佳实战 Spark 更高性能的算子 引言 我们谈大数据性能调优,到底在谈什么,它的本质 ...
- JVM性能调优监控工具专题一:JVM自带性能调优工具(jps,jstack,jmap,jhat,jstat,hprof)
性能分析工具jstatjmapjhatjstack 前提概要: JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps.jsta ...
- JVM性能调优(3) —— 内存分配和垃圾回收调优
前序文章: JVM性能调优(1) -- JVM内存模型和类加载运行机制 JVM性能调优(2) -- 垃圾回收器和回收策略 一.内存调优的目标 新生代的垃圾回收是比较简单的,Eden区满了无法分配新对象 ...
随机推荐
- phpStorm安装方法
1)下载 http://big2.h5gamen.com/soft/jetbrainscrack-2.6.2.zip 放到phpstorm安装目录下的lib文件夹 如放到f盘 F:\PhpStorm ...
- Vue之九数据劫持实现MVVM的数据双向绑定
vue是通过数据劫持的方式来做数据绑定的,其中最核心的方法便是通过Object.defineProperty()来实现对属性的劫持,达到监听数据变动的目的. 如果不熟悉defineProperty,猛 ...
- spring - boot 监控管理模块搭建
Spring-Actuator是Spring-boot对应用监控的集成模块,提供了我们对服务器进行监控的支持,使我们更直观的获取应用程序中加载的应用配置.环境变量.自动化配置报告等. 使用Spring ...
- Java多线程:synchronized关键字和Lock
一.synchronized synchronized关键字可以用于声明方法,也可以用来声明代码块,下面分别看一下具体的场景(摘抄自<大型网站系统与Java中间件实践>) 案例一:其中fo ...
- RabbitMQ 发布订阅持久化
RabbitMQ是一种重要的消息队列中间件,在生产环境中,稳定是第一考虑.RabbitMQ厂家也深知开发者的声音,稳定.可靠是第一考虑,为了消息传输的可靠性传输,RabbitMQ提供了多种途径的消息持 ...
- VS2017调试器无法附加到IIS进程(w3wp.exe)
问题描述: 当使用VS2017-> 调试->附加到进程来调试IIS进程(w3wp.exe)时,报错"无法附加到进程,已附加了一个调试器" 为了解决这个问题花了不少时间, ...
- ssh框架-Struts2(一)
Struts2 概述 用我们自己的话来说: struts是web层框架, 相当于Servlet 作用: 1. 获得请求参数 2. 调用业务 3. 分发转向 常用的WEB层框架 Struts2入门 1. ...
- 使用SecureCRTP 连接生产环境的web服务器和数据库服务器
一.使用SecureCRTP 连接生产环境的web服务器 首先,需要知道以下参数信息: 1.web服务器的ip地址 2.服务器的端口号 3.会话连接的用户名和密码 4.服务器的用户名 ...
- MSSQL 2000 错误823恢复案例
一.故障描述 MSSQL Server 2000 附加数据库错误823,附加数据库失败.数据库没有备份,不能通过备份恢复数据库,急需恢复数据库中的数据. 二.故障分析SQL Server数据库 823 ...
- ELK学习总结(2-6)elk的mapping
1.什么是映射 映射:创建索引的时候,预先定义字段的类型及相关属性 作用:这样会让索引建立的更加细致和完善,如:是否存储.使用何种分析器.重要级别 分类:静态映射和动态映射 2.字段类型:string ...