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区满了无法分配新对象 ...
随机推荐
- 最小化安装CentOS7的网卡设置
实验环境:CentOS 7 Minimal Installation 64bit (1511) 最小化安装CentOS 7 后,查看网卡的信息让人很意外,因为网卡的命名规则变了,网卡的名字让人很难懂. ...
- Ubuntu安装Anaconda
安装Anaconda的最简单方法是下载最新的Anaconda安装程序bash脚本,然后运行它. 在Anaconda Downloads页面找到最新版本的Anaconda for Python 3 .当 ...
- clumsy模拟客户端网络差的场景的使用
1.为什么需要模拟客户端网络差的情况? a. 研发环境的网络配置一般较高,网络响应快,不容易出现网络故障,但是客户使用的网络环境千差万别,不排除使用过程中遇到网络故障的情况. b.程序有些时候是多线程 ...
- Oracle修改字段类型方法小技巧
有一个表名为tb,字段段名为name,数据类型nchar(20). 1.假设字段数据为空,则不管改为什么字段类型,可以直接执行:alter table tb modify (name nvarchar ...
- TensorFlow拟合线性函数
TensorFlow拟合线性函数 简单的TensorFlow图构造 以单个神经元为例 x_data数据为20个随机 [0, 1) 的32位浮点数按照 shape=[20] 组成的张量 y_data为 ...
- 漫谈Java IO之 Netty与NIO服务器
前面介绍了基本的网络模型以及IO与NIO,那么有了NIO来开发非阻塞服务器,大家就满足了吗?有了技术支持,就回去追求效率,因此就产生了很多NIO的框架对NIO进行封装--这就是大名鼎鼎的Netty. ...
- alpha冲刺第二天
一.合照 二.项目燃尽图 三.项目进展 图形界面基本完成 接口文档框架完成,接下来将会不断细化填充 登录界面向服务器请求数据进行ing 四.明日规划 1.注册登录接口能够完成 2.研究idea实现获得 ...
- Beta第七天
听说
- c语言一,二数组
一.PTA实验作业 题目1:7-4 简化的插入排序 1. 本题PTA提交列表 2. 设计思路 1.定义整形变量N,temp,i. 2.输入N 3.通过for(i=1;i<=N;i++)的循环语句 ...
- django搭建web (五) views.py
http请求: HttpRequest http响应: HttpResponse 所在位置:django.http isinstance(request,HttpResponse) True-> ...