基于CW32的多功能函数信号发生器设计 - 嘉立创EDA开源硬件平台

编辑器版本 ×
标准版 Standard

1、简单易用,可快速上手

2、流畅支持300个器件或1000个焊盘以下的设计规模

3、支持简单的电路仿真

4、面向学生、老师、创客

专业版 professional

1、全新的交互和界面

2、流畅支持超过3w器件或10w焊盘的设计规模,支持面板和外壳设计

3、更严谨的设计约束,更规范的流程

4、面向企业、更专业的用户

专业版 基于CW32的多功能函数信号发生器设计

简介:以CW32为控制核心,AD9910及W25Q64为外围电路,设计一款函数信号发生器,支持正弦、三角、方波(频率、幅度、相位可调)等26种波形输出,支持扫频、扫幅、扫相、调制等功能。

开源协议: Public Domain

(未经作者授权,禁止转载)

已参加:“暖冬造物迎新年”征集令

创建时间: 2023-12-18 20:23:15
更新时间: 2024-01-10 18:35:47
描述
# 一、实物展示及部分制造流程展示: ![IMG_1871.JPG](//image.lceda.cn/pullimage/7p5KbdPAJ72oqkA5lixwkOzUobttGRmAekdcAyiQ.jpeg) ![IMG_1872.JPG](//image.lceda.cn/pullimage/DlxmkO5ZZxyRMFiENheGK6rB83qQaikF3HxAPCkS.jpeg) ![IMG_1876.JPG](//image.lceda.cn/pullimage/8Wk89mtZIe8tcxmCC716mY2HOIrFcM1GBV0U7EGt.jpeg) ![IMG_1878.JPG](//image.lceda.cn/pullimage/IHMqkrjx8ixYBEEG1AXzFH16wyhj86c86FHV7euX.jpeg) ![IMG_1879.JPG](//image.lceda.cn/pullimage/KY7rGu9sPIFJkbuN1zo5uLJ9x8kMG3WDcM9a8cLi.jpeg) ![IMG_1883.JPG](//image.lceda.cn/pullimage/vikXZvL0q7sFS4dv7YewMoE6xwFa1DrtbCdzttUj.jpeg)![IMG_1884.JPG](//image.lceda.cn/pullimage/XrRkzuEosAQhWbGzh71yUHISv9iZmOqw8R26u9iJ.jpeg) ![IMG_1885.JPG](//image.lceda.cn/pullimage/gZKWTBpuD77HhvFfEMmOK3FtP17dQsPmy3cKlJ6U.jpeg) ![IMG_1886.JPG](//image.lceda.cn/pullimage/t38Mdt9krR9arLruzThrbAJ7Njf25r9vZVbQ4YHg.jpeg) ![IMG_1889.JPG](//image.lceda.cn/pullimage/C6rbFVlYGwq8JTkAmozEmBRzlviWJXYQNa1J3JHq.jpeg)![IMG_1890.JPG](//image.lceda.cn/pullimage/O1pizz6XCyTzgYWqPQVNumK1Zs6BcxyOnmRUg3bw.jpeg) ![IMG_1891.JPG](//image.lceda.cn/pullimage/irOQY4oTfxkQXeS4Y7YMei4241LYCqkfVmA2XlNg.jpeg) # 实物展示链接:[演示视频](https://www.bilibili.com/video/BV19k4y1D7my/) # 二、详细功能说明 ## 本设计以CW32F030系列单片机为系统控制核心,以AD9910模块作为波形生成系统,HMI4.3寸触摸屏作为人机交互接口,用于设定相关参数,W25Q64作为数据存储设备,以简单的外围电路结构,设计一款多功能函数信号发生器,基本功能GUI界面如图所示。 ![image.png](//image.lceda.cn/pullimage/jzsWShjglJBbGlwMBayD5upETsBnpUhzVhJ4wbww.png) # 项目基本功能包含: ## 1.1-420MHz正弦波输出. ## 2.3.7-244Khz三角波输出. ## 3.3.7-244Khz方波输出. ## 4.其他常见波输出(其他常见14种波形输出). ## 5.单频调制可进行以下功能选择 ### (1)AM调制. ### (2)PM调制. ### (3)FM调制. ### (4)2ASK. ### (5)2PSK. ### (6)2FSK. ### 6.扫描功能可进行以下功能选择 ### (1)扫频. ### (2)扫幅. ### (3)扫相. ### 7.谐波调制可选择以下功能选择 ### (1)FM. ### (2)AM. ### (3)PM. ### 8.跳频(该功能暂未实现) ### 8.其他(拓展功能). # 详细功能说明: ### 1.正弦波输出模式:在正弦波输出模式下,频率、幅度、相位通过HMI触摸屏可调,频率范围:1Hz-450MHz,步进1Hz,幅度0-100%可调,步进1%,相位0-360度可调,步进1度。GUI界面如下图所示. ![image.png](//image.lceda.cn/pullimage/kZwN9uLTznTDSQhmGCfwUxs28ajCPTayBalMUzoS.png) ### 2. 三角波输出模式:在三角波模式下,频率、宽度可调,频率步进1Hz,最大244KHz,在三角波输出模式下提供两种波形输出模式. ### 1.连续双向扫描:播放完一个波形后,波形倒放. ### 2.连续循环扫描:连续播放一个波形 ### GUI界面如图所示 ![image.png](//image.lceda.cn/pullimage/DT0usI5VG1ewMpF86HYy7mLr7nTpjlAM32yGLpK0.png) ### 3.方波输出模式:在方波输出模式下波形宽度、频率可调,宽度步进5%,频率步进1Hz。 ### GUI界面如图所示 ![image.png](//image.lceda.cn/pullimage/1MxhUZZwY7Il47uyFn0rw9IIfpoX1bsfkb51hdgG.png) ### 4.其他波形输出模式:输出波形有以下14种常见的波形进行选择: ### (1)斩波. ### (2)全波. ### (3)半波. ### (4)对数. ### (5)削顶正弦. ### (6)辛格函数. ### (7)衰减震荡. ### (8)削顶三角. ### (9)正指数. ### (10)负指数. ### (11)正阶梯. ### (12)负阶梯. ### (13)洛伦兹. ### (14)高斯. ### 选择GUI界面如图所示 ![image.png](//image.lceda.cn/pullimage/CqMqhTmJduRTeCXhK5ACAbyMbMVziVQE4cGQNnpE.png) ### 在此模式下,波形频率可调,波形输出模式可调。提供两种波形输出模式 ### 1.连续双向扫描 ### 2.连续循环扫描 ### 对应波形输出界面如图所示 ![image.png](//image.lceda.cn/pullimage/2C15TmyoLZzpmZ7X6ZIlVTWfOB03a0z3tnK99K9F.png) ### 通过点击输出波形按钮,可按照顺序切换1种波形输出。 ### 通过点击确认可进行波形输出,在确认点击按键按下后,再次按下可变为取消按键,取消波形输出.返回按键按下,返回上一级菜单. ## 4.单频调制GUI如下图所示 ![image.png](//image.lceda.cn/pullimage/tnauBz9Se5sczzPHOlKw3wDnIyR2w4J6TfFKjqJ6.png) # 4.单频调制模式下提供 ## (1)FM调制: ### 界面GUI如下图所示 ![image.png](//image.lceda.cn/pullimage/ZmnMTRWktP3UnVbpY5F0OIKCXcx4s3aQPAftCK7x.png) # 在此模式下可设定FM调制的以下参数: ### 1.起始频率. ### 2.终止频率. ### 3.步进频率. ### 4.波形幅度. ### 5.波形相位. ## (2)AM调制 ### GUI如下图所示 ![image.png](//image.lceda.cn/pullimage/t2WioGYuFomeMeMYBRxjx1wCRdvdh7phs4PGBaSS.png) ### 在此模式下可设定AM调制的以下参数: ### 1.起始幅度. ### 2.终止幅度. ### 3.步进幅度. ### 4.波形频率. ### 5.波形相位. ## (3)PM调制 ### GUI如下图所示 ### ![image.png](//image.lceda.cn/pullimage/it4PpT2fe5eqAgOFzY2gNl7OseLRRfxhGqIHRd7G.png) ## 在此模式下可设定PM调制的以下参数: ### 1.起始相位. ### 2.终止相位. ### 3.步进相位. ### 4.波形频率. ### 5.波形幅度. ## (4)2FSK调制 ### GUI如下图所示 ![image.png](//image.lceda.cn/pullimage/jIqKVepBrvTTCcxN0XugVZKuQJjKNRe5SKjKd48u.png) ### 在此模式下可设定2FSK调制的以下参数: ### 1.起始频率. ### 2.终止频率. ### 3.起始频率持续时间. ### 4.起始频率持续时间. ### 5.波形幅度. ### 5.波形相位. ## (5)2ASK调制 ### GUI如下图所示 ![image.png](//image.lceda.cn/pullimage/3A82zPAWylxweTlgMFWTbv3SbWXFUGfZ1ks0aWaV.png) ### 在此模式下可设定2ASK调制的: ### 1.起始幅度. ### 2.终止幅度. ### 3.起始幅度持续时间. ### 4.起始幅度持续时间. ### 5.波形频率. ### 5.波形相位. ## (5)2PSK调制 ### GUI如下图所示 ![image.png](//image.lceda.cn/pullimage/SeZyytAF2A3laR6J5zBh1r5BV3KCwOYhqvqOToHL.png) ### 在此模式下可设定2PSK调制的以下参数: ### 1.起始相位. ### 2.终止相位. ### 3.起始相位持续时间. ### 4.起始相位持续时间. ### 5.波形频率. ### 5.波形幅度. # 4.扫描模式下GUI如下图所示 ![image.png](//image.lceda.cn/pullimage/KpQAou3PJe9JoYwEStnyOYDuUtVJDsPx9IqwldFj.png) # 扫描模式下功能1:扫频 # 扫频功能下三种不同扫频模式GUI如下图所示 ## 上扫频GUI ![image.png](//image.lceda.cn/pullimage/lNDxxenFzX7npoyUBagKSfbbuT82rNqMmkQuA3fY.png) ## 下扫频GUI ![image.png](//image.lceda.cn/pullimage/PUw6IpmkRP0zgG0E3oSyxDbpbEMAJBnedW6U1Ysg.png) ## 上下扫频GUI ![image.png](//image.lceda.cn/pullimage/rqVkjraDElngzf5i7EUzTpLFCNrLjFWnys3RpbPA.png) ## 在扫频模式下可以设定以下参数用于扫频控制: ### 1.扫频上限频率 ### 2.扫频下限频率 ### 3.扫频步进频率 ### 4.扫频幅度 ### 5.扫频相位 ### 6.扫频时间间隔 ### 7.扫频DRC引脚时间间隔 ### 8.扫频下限频率 ### 9.选择扫频方式:上扫频、下扫频、上下扫频 # 扫描模式下功能2:扫幅 ### 扫幅功能GUI如下图所示 ## 上扫幅GUI ![image.png](//image.lceda.cn/pullimage/aCbRTU8v9WvR1D3jMTaGrUQcfeLpNW58bF8d7Nnn.png) ## 下扫幅GUI ![image.png](//image.lceda.cn/pullimage/un2ivBifPRmBhOMP4BOSb7hnfOCcrgxFvk7CQqIq.png) ## 上下扫幅GUI ![image.png](//image.lceda.cn/pullimage/XrNDjYPYFQhvk1Bw3W0MAfNR6V5h3eFZj0qJgYJa.png) ## 在扫幅模式下可以设定以下参数用于扫幅控制: ### 1.扫幅上限幅度 ### 2.扫幅下限幅度 ### 3.扫幅步进幅度 ### 4.扫幅频率 ### 5.扫幅相位 ### 6.扫幅时间间隔 ### 7.扫幅DRC引脚时间间隔 ### 9.选择扫幅方式:上扫幅、下扫幅、上下扫幅 # 扫描模式下功能3:扫相 ### 扫幅功能GUI如下图所示 ### 上扫相GUI ![image.png](//image.lceda.cn/pullimage/Ixd3TVGROTPEECx3UoeC238LUipABFyZDeun3VJI.png) ### 下扫相GUI ![image.png](//image.lceda.cn/pullimage/8VW1kvmZqloRnD2XjZxF4nSHqYgUVON8Eoeihcbh.png) ### 上下扫相GUI ![image.png](//image.lceda.cn/pullimage/mag8z528p0nXAfNWv8PrRqASv6dVz88WJbZhyXdp.png) ### 在扫相模式下可以设定以下参数用于扫相控制: ### 1.扫相上限幅度 ### 2.扫相下限幅度 ### 3.扫相步进幅度 ### 4.扫幅频率 ### 5.扫相相位 ### 6.扫相时间间隔 ### 7.扫相DRC引脚时间间隔 ### 9.选择扫相方式:上扫相、下扫相、上下扫相 # 谐坡调制功能 ### 谐坡调制GUI如下图所示: ![image.png](//image.lceda.cn/pullimage/ceSZ0sSzze4yUektixVbKVxBB3TKfp5VzqfxG8N3.png) # 谐波调制功能1: FM调制 ### 谐波FM调制GUI如下图所示: ![image.png](//image.lceda.cn/pullimage/n00FueQk68Skrgwy3d2iLwbVBtoEbhD25LqFPhAf.png) ## 在此模式下可设定以下参数用于FM调制 ### 1.FM调制起始频率 ### 2.FM调制终止频率 ### 3.FM调制幅度 ### 4.FM调制相位 ### 5.FM调制斜率维持时间 # 谐波调制功能2: AM调制 ### 谐波AM调制GUI如下图所示: ![image.png](//image.lceda.cn/pullimage/k0V9AoMpr0qhBooj0rznx0CqlPXBF9tRhHpIiJ2c.png) ## 在此模式下可设定以下参数用于AM调制 ### 1.AM调制起始幅度 ### 2.AM调制终止幅度 ### 3.AM调制频率 ### 4.AM调制相位 ### 5.AM调制斜率维持时间 # 谐波调制功能3: PM调制 ## 谐波AM调制GUI如下图所示: ![image.png](//image.lceda.cn/pullimage/0iTh3o93Y0GEaOhLPRBhHnbLFBVyt9RvAfruEnnx.png) ## 在此模式下可设定以下参数用于PM调制 ### 1.PM调制起始相位 ### 2.PM调制终止相位 ### 3.PM调制频率 ### 4.PM调制幅度 ### 5.PM调制斜率维持时间 # 三、设计硬件说明 ## 本项目主要由CW32F030单片机、AD9910模块、HMI4.3寸触摸屏、W25Q64存储芯片构成,硬件不存在复杂的数字或模拟电路,最复杂的应该是AD9910控制板的电路。可参考该账户下其他开源项目进行查阅详细说明。 ## CW32的GPIO口占用少,但功能相对强大,除跳频功能外其他全部完成。 # 因此对硬件电路不进行过多赘述,可以将整个硬件系统理解为:一个CW32最小系统(小蓝板)+一块HMI触摸屏+一个AD9910构成,最难部分均在软件代码设计. # 对于ASK、PSK、FSK、AM、PM、FM、扫幅、扫频、扫相这些需要对高频电子这门课需要较深的理解,对实际应用有一定认知...我也不知道怎么进行论述,比如可以通过扫频确定一个电容的容量之类的...具体实现原理...请查相关资料。 # 硬件电路电源部分简单说明 # 电源电路:本项目供电电路由Type-C电路和电池供电电路组合而成,当Type-C悬空时,由电池进行供电,当Type-C接口接入时,由Type-C进行系统供电。流程图图下图所示。 ![image.png](//image.lceda.cn/pullimage/ytT4RYwX5a8o4xhtgp6xF4pGtWlACgkZpzRlvdbk.png) ## 电路结构如下图所示 ![image.png](//image.lceda.cn/pullimage/CvljnpH2D2eVF9r8ddlyoZ4eFTTEP0HBQXV9kFDi.png) ## 电源流向:从左向右 ## 在电路结构中存在这些屏蔽掉所有接口的电路,是用于定位孔绘制和3D模型绘制,在实际电路中无任何电气意义。 ![image.png](//image.lceda.cn/pullimage/ZblVDxaMT6XjaNZxgeGOkOGGah3SiS2FbXtzEZdg.png) # 对于AD9910的电路,请参考我的其他开源项目进行的详细说明,在本项目中不进行过多论述。 # 本项目的原理图很简单,复杂的只有供电电路。 # PCB设计说明 # 在本项目下只有两款PCB,第一款是核心板,第二款是AD9910接口的转接板,将2.54mm的排针接口转为PFC接口,用于跟核心板上的FPC接口进行连接,构成一个集成化的系统,避免通过线束的连接方式,在该PCB上开出一个开口,用于将FPC排线引出。 ![Snipaste_2024-01-03_16-15-52.png](//image.lceda.cn/pullimage/0FHJvRFv5dFcIAJpH3WAEDNjH3JoM1l2dn68MRTJ.png) # 为降低板子的实际高度,该板尽量薄,因此我打板的时候选择厚度为1.2mm. # 主板中间开出一个很大的镂空区域,用于将AD9910放在其中。![2.png](//image.lceda.cn/pullimage/vkXxZpWCYhrRFVaGig0Nyhsjb44AF7UlQsbTfWDu.png) ## 通过镂空区域和底部的螺丝柱,可以将AD9910完美的固定在上面。从节省成本上考虑,该部分可以舍去不用,只用底层的螺丝柱即可达到固定效果。板子大于10x10mm,不能使用免费打扮,双层板打板要40多! # 三、设计软件说明 # 软件部分是整个设计的终点,在硬件电路设计时,一个小下午,硬件电路设计时用了一个多月,涉及的内容比较多。软件运行流程如下图所示。 ![image.png](//image.lceda.cn/pullimage/ufEm2isMDbKdqePFvsPwoOKfe6w5HGau6G0IIDdR.png) # 4.3寸HMI串口屏代码编写. ## 串口通信代码流程如下图所示 ![image.png](//image.lceda.cn/pullimage/gtA57JRRfdAmru0ZFWupT5cGCjkIzR5Lc0ghdJ7e.png) ## 串口屏运行流程如下图所示,所有逻辑代码均遵循以下原则 ![image.png](//image.lceda.cn/pullimage/Lsqz9m5WaW4EdFf99PGaC8VasgjvNxan8qJ4Me2x.png) ### 受限于CW32的片内资源,无法应用一些功能强大的RGB屏幕,因此选用MHI串口屏进行人机交互,实验结果表明,人机交互状态良好,基本实现预定功能。 ## 其中HMI串口屏只用于发送预定帧结构的数据,单片机进行解算后进行相应,单片机不对HMI串口屏进行其他控制。 # 串口屏帧结构如下图所示: ![image.png](//image.lceda.cn/pullimage/Lqaj7pMj5dlB0cfVDlvtNv63HIbFC1CA6kehTxav.png) ### 帧结构构成:帧头+4位控制数据+帧尾(0A+数据位或标志位1+数据位或标志位2+数据位或标志位3+数据位或标志位3+帧尾) ## 帧头:0A,数据接收允许标志 ## 数据:屏幕上设定参数构成,最大4个位 ### 帧尾:A0,数据接收结束标志位 ## 如发送一个频率参数,其HMI发送的帧结构为:0A EF 1A 03 06 A0,单片机进行接收,控制系统响应流程如下图所示。 ![image.png](//image.lceda.cn/pullimage/p05ev0QhyMtK79e5RIKBZ8bEl1pxkEbdXPbFibLh.png) ### 具体逻辑代码请查看上传的HMI工程,该模块很好上手,在对其进行编程时,我只会画火柴人,UI界面不怎么好看,但是代码逻辑很完善。 ### 在液晶显示部分,你可以理解为你要发什么数据、什么时候发、发了之后怎么样! # 2.W25Q64代码编写 ## 在本项目中,还是CW32片内Flash的问题,我只能用W25Q64进行波形数据存储,在CW32下只能定义一个4096大小的数据,因此智能一此次的往对应的4K字节扇区写入4096个波形数据。 ## 在使用W25Q64时应明确: ## 1.你要把数据存到(128块每块64)块中的哪一块。哪一块的那个扇区(32K),哪个扇区的那个区域(4K),那个区域的那个页(256字节)的地址。 ## 本项目存储数据都是线性存储,都是4096个数据,相当于一次寸一个区域,一个32K的扇区可以寸8个波形,一个64K的块可以存16个波形,因此需要大约3个快进行数据存储。存入结构路程如下图所示。 ![image.png](//image.lceda.cn/pullimage/j7MRG6mY5pbVFpZRJUJdaMxyCMT5WvSnTwFXIY3M.png) ### 波形写入步骤如下图所示 ![image.png](//image.lceda.cn/pullimage/WLfO9mI6qxrNW0xYea63vd1rjuTIXEL1kUKrhuX0.png) ### 1.波形数据存入4096大小的数组:const uint8_t Wave_Date[4096] ![image.png](//image.lceda.cn/pullimage/3piutvTxW8X57yx59OV0yr5JWrcpuNVy5wXZnlrv.png) ### 2.选择写入的4K扇区,用十进制数表示,从0开始向上递增 ![image.png](//image.lceda.cn/pullimage/0if5d7rjKkSChgNa6ziv4u5zcJTxJPB82HhOGrLg.png) ### 3.运行写入代码将4096大小的波形数据拆分为256大小,进行分页写入,刚好可以写满一个4K扇区.代码如下所示。 ``` for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i];} W25Q64_PageWrite(Wdate,0+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256];} W25Q64_PageWrite(Wdate,1+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*2];} W25Q64_PageWrite(Wdate,2+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*3];} W25Q64_PageWrite(Wdate,3+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*4];} W25Q64_PageWrite(Wdate,4+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*5];} W25Q64_PageWrite(Wdate,5+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*6];} W25Q64_PageWrite(Wdate,6+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*7];} W25Q64_PageWrite(Wdate,7+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*8];} W25Q64_PageWrite(Wdate,8+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*9];} W25Q64_PageWrite(Wdate,9+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*10];} W25Q64_PageWrite(Wdate,10+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*11];} W25Q64_PageWrite(Wdate,11+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*12];} W25Q64_PageWrite(Wdate,12+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*13];} W25Q64_PageWrite(Wdate,13+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*14];} W25Q64_PageWrite(Wdate,14+page); for(i=0;i<256;i++) {Wdate[i]=Wave_Date[i+256*15];} W25Q64_PageWrite(Wdate,15+page); ``` ### 4.运行读取代码,查看数据写入情况,可确认数据是否正常写入,读取数据不受限制,一次读取4096个字节。 ``` W25Q64_Read(Date,0x29000,4096); for(i=0;i<4096;i++) { printf("Wave[%d]=%x\r\n",i,Date[i]); } ``` #### 以上完成数据写入代码,写入的波形需要一个个写入!!!这个是个很繁琐的过程,一定要做好记录! # 别问位啥不一次性写入,因为RAM就10K ,你定义两个4096大小的数组,直接硬件异常,芯片直接歇菜! ## 3.串口代码注解 ### 串口代码只要是对传输过来的数据进行相应,必须是0A开头,必须是0A结尾,不然数据无效。 ## 接收流程是: ### 1.收到A0--开始接收数据,否则无效 ### 2.收到0A--结束数据否则无效 ### 3.对接收数据根据帧结构进行基本解算,并对相应标志位赋值,告诉主函数是什么数据来了,以下是解算代码。 ``` if(USART_GetITStatus(CW_UART1, USART_IT_RC) != RESET) { recv_dat = USART_ReceiveData_8bit(CW_UART1); //数据结构 FF 00 01 02 03 FE // 帧头 + 帧内容 + 帧尾 switch(recv_state) { case 0: if(recv_dat==0x0A) { recv_state=1;//是包头标志位置于1 rxd_index=0; }else {recv_state=0;}//不是处于等待状态 break; case 1: rxd_buf[rxd_index]=recv_dat; rxd_index++; if(rxd_index>=4) { recv_state=2; } break; case 2: if(recv_dat==0xA0) { rxd_flag=1; if(rxd_buf[0]==0x00){rxd_flag=1; printf("1\n\r");}//频率档位标志位 if(rxd_buf[0]==0x01){rxd_flag=2; printf("2\n\r");}//频率参数设定标志位 if(rxd_buf[0]==0x02){rxd_flag=3; printf("3\n\r");}//幅度参数设定标志位 if(rxd_buf[0]==0x03){rxd_flag=4; printf("4\n\r");}//相位参数设定标志位 /**进入正弦页面和离开正弦页面判断标志位***/ if(rxd_buf[0]==0x04){rxd_flag=5; printf("5\n\r");}//进入正弦界面 if(rxd_buf[0]==0x05){rxd_flag=6; printf("6\n\r"); if(Get_Stat()==0){MAS_REST_HIGH; }} //返回主界面 //进入三角波模式 if(rxd_buf[0]==0xAA){rxd_flag=7; printf("7\n\r");}//频率 if(rxd_buf[0]==0xA1){rxd_flag=8; printf("8\n\r");}//宽 if(rxd_buf[0]==0xA2){rxd_flag=9; printf("9\n\r");}//模式 if(rxd_buf[0]==0xA3){rxd_flag=10; printf("10\n\r");}//档位 if(rxd_buf[0]==0xA4){rxd_flag=11; printf("11\n\r");//开启或关闭 if(Get_Stat()==0){MAS_REST_HIGH; } if(Get_Stat()==1){Init_ad9910();} }//开启或关闭 //进入方波模式 if(rxd_buf[0]==0xB0){rxd_flag=12; printf("12\n\r");}//频率档位 if(rxd_buf[0]==0xB1){rxd_flag=13; printf("13\n\r");}//占空比 if(rxd_buf[0]==0xB2){rxd_flag=14; printf("14\n\r");}//播放模式 if(rxd_buf[0]==0xB3){rxd_flag=15; printf("15\n\r");}//频率 if(rxd_buf[0]==0xB4){rxd_flag=16; printf("16\n\r"); if(Get_Stat()==0){MAS_REST_HIGH; } if(Get_Stat()==1){Init_ad9910();} }//开启或关闭 //其他波形处理函数 //***************扫频模式************************/ if(rxd_buf[0]==0x70){rxd_flag=17; printf("16上限频率\n\r");}//扫频上限 if(rxd_buf[0]==0x71){rxd_flag=18; printf("18下限频率\n\r");}//扫频下限 if(rxd_buf[0]==0x72){rxd_flag=19; printf("19步进频率\n\r");}//扫频步进 if(rxd_buf[0]==0x73){rxd_flag=20; printf("20幅度\n\r");}//扫频幅度 if(rxd_buf[0]==0x74){rxd_flag=21; printf("21相位\n\r");}//扫频相位 if(rxd_buf[0]==0x75){rxd_flag=22; printf("22斜率档位\n\r");}//斜率时间档位 if(rxd_buf[0]==0x76){rxd_flag=23; printf("23斜率数据\n\r");}//斜率 if(rxd_buf[0]==0x77){rxd_flag=24; printf("24DRC时间间隔\n\r");}//DRC时间间隔 if(rxd_buf[0]==0x78){rxd_flag=25; printf("25扫频模式\n\r");}//扫频模式 if(rxd_buf[0]==0x79){rxd_flag=26; printf("26开启或关闭\n\r"); if(Get_Stat()==0){MAS_REST_HIGH; } if(Get_Stat()==1){Init_ad9910();} } //开启或关闭扫频 //**************扫幅模式************************/ if(rxd_buf[0]==0x80){rxd_flag=27; printf("27扫幅上限\n\r");} if(rxd_buf[0]==0x81){rxd_flag=28; printf("28扫幅下限\n\r");} if(rxd_buf[0]==0x82){rxd_flag=29; printf("29扫幅步进\n\r");} if(rxd_buf[0]==0x83){rxd_flag=30; printf("30扫幅频率\n\r");} if(rxd_buf[0]==0x84){rxd_flag=31; printf("31扫幅相位\n\r");} if(rxd_buf[0]==0x85){rxd_flag=32; printf("32时间档位\n\r");} if(rxd_buf[0]==0x86){rxd_flag=33; printf("33时间\n\r");} if(rxd_buf[0]==0x87){rxd_flag=34; printf("34DRC时间间隔\n\r");} if(rxd_buf[0]==0x88){rxd_flag=35; printf("35扫幅方式\n\r");} if(rxd_buf[0]==0x89){rxd_flag=36; printf("36扫幅开启或关闭\n\r"); if(Get_Stat()==0){MAS_REST_HIGH; } if(Get_Stat()==1){Init_ad9910();} } //**************扫相模式************************/ if(rxd_buf[0]==0xC7){rxd_flag=37; printf("32扫相上限\n\r");} if(rxd_buf[0]==0xC8){rxd_flag=38; printf("38扫相下限\n\r");} if(rxd_buf[0]==0xC9){rxd_flag=39; printf("39扫相步进\n\r");} if(rxd_buf[0]==0xCA){rxd_flag=40; printf("40扫相频率\n\r");} if(rxd_buf[0]==0xCB){rxd_flag=41; printf("41扫相幅度\n\r");} if(rxd_buf[0]==0xCC){rxd_flag=42; printf("42扫相时间档位\n\r");} if(rxd_buf[0]==0xCD){rxd_flag=43; printf("43扫相时间\n\r");} if(rxd_buf[0]==0xCE){rxd_flag=44; printf("44扫相DRC时间间隔\n\r");} if(rxd_buf[0]==0xCF){rxd_flag=45; printf("45扫相方式\n\r");} if(rxd_buf[0]==0xFA){rxd_flag=46; printf("46扫相开启或关闭\n\r"); if(Get_Stat()==0){MAS_REST_HIGH; } if(Get_Stat()==1){Init_ad9910();} } //FM模式参数 if(rxd_buf[0]==0xF0){rxd_flag=47; printf("47FM起始频率\n\r");} if(rxd_buf[0]==0xF1){rxd_flag=48; printf("48FM终止频率\n\r");} if(rxd_buf[0]==0xF2){rxd_flag=49; printf("49FM步进频率\n\r");} if(rxd_buf[0]==0xF3){rxd_flag=50; printf("50FM频率斜率时间\n\r");} if(rxd_buf[0]==0xF4){rxd_flag=51; printf("51FM幅度\n\r");} if(rxd_buf[0]==0xF5){rxd_flag=52; printf("52FM相位\n\r");} if(rxd_buf[0]==0xF6){rxd_flag=53; printf("53FM开启或关闭标志位\n\r"); if(Get_Stat()==0){MAS_REST_HIGH; } if(Get_Stat()==1){Init_ad9910();} } //AM模式参数 if(rxd_buf[0]==0x20){rxd_flag=54; printf("47AM起始幅度\n\r");} if(rxd_buf[0]==0x21){rxd_flag=55; printf("48AM终止幅度\n\r");} if(rxd_buf[0]==0x22){rxd_flag=56; printf("49AM步进幅度\n\r");} if(rxd_buf[0]==0x23){rxd_flag=57; printf("50AM频率斜率时间\n\r");} if(rxd_buf[0]==0x24){rxd_flag=58; printf("51AM频率\n\r");} if(rxd_buf[0]==0x25){rxd_flag=59; printf("52AM相位\n\r");} if(rxd_buf[0]==0x26){rxd_flag=60; printf("53AM开启或关闭标志位\n\r"); if(Get_Stat()==0){MAS_REST_HIGH; } if(Get_Stat()==1){Init_ad9910();} } //PM模式参数 if(rxd_buf[0]==0x30){rxd_flag=61; printf("61PM起始相位\n\r");} if(rxd_buf[0]==0x31){rxd_flag=62; printf("62PM终止相位\n\r");} if(rxd_buf[0]==0x32){rxd_flag=63; printf("63PM步进相位\n\r");} if(rxd_buf[0]==0x33){rxd_flag=64; printf("64PM频率斜率时间\n\r");} if(rxd_buf[0]==0x34){rxd_flag=65; printf("65PM频率\n\r");} if(rxd_buf[0]==0x35){rxd_flag=66; printf("66PM幅度\n\r");} if(rxd_buf[0]==0x36){rxd_flag=67; printf("67PM开启或关闭标志位\n\r"); if(Get_Stat()==0){MAS_REST_HIGH; } if(Get_Stat()==1){Init_ad9910();} } //单频调制FM if(rxd_buf[0]==0x40){rxd_flag=68; printf("68单频调制FM起始频率\n\r");} if(rxd_buf[0]==0x41){rxd_flag=69; printf("69单频调制FM终止频率\n\r");} if(rxd_buf[0]==0x42){rxd_flag=70; printf("70单频调制FM步进频率\n\r");} if(rxd_buf[0]==0x43){rxd_flag=71; printf("71单频调制FM幅度\n\r");} if(rxd_buf[0]==0x44){rxd_flag=72; printf("72单频调制FM相位\n\r");} if(rxd_buf[0]==0x45){rxd_flag=73;stateFM=0; printf("73单频调制FM开启或关闭标志位\n\r"); if(Get_Stat()==0){Init_ad9910(); Break_FM=1;ad9910_reset(1); MAS_REST_HIGH;} if(Get_Stat()==1){Init_ad9910(); Test(); MAS_REST_LOW; Break_FM=0;} } //在此直接解算,直接关闭 //单频AM调制 if(rxd_buf[0]==0x50){rxd_flag=74; stateFM=0;printf("74单频调制AM起始幅度\n\r");} if(rxd_buf[0]==0x51){rxd_flag=75; printf("75单频调制AM终止幅度\n\r");} if(rxd_buf[0]==0x52){rxd_flag=76; printf("76单频调制AM步进幅度\n\r");} if(rxd_buf[0]==0x53){rxd_flag=77; printf("77单频调制AM频率\n\r");} if(rxd_buf[0]==0x54){rxd_flag=78; printf("78单频调制AM相位\n\r");} if(rxd_buf[0]==0x55){rxd_flag=79; stateAM=0;printf("79单频调制AM开启或关闭标志位\n\r"); if(Get_Stat()==0){ Init_ad9910(); stateAM=2;ad9910_reset(1); MAS_REST_HIGH; //关闭 } if(Get_Stat()==1){Init_ad9910(); Test(); MAS_REST_LOW; stateAM=0;} } //在此直接解算,直接关闭 //单频PM调制 if(rxd_buf[0]==0x60){rxd_flag=80; stateFM=0;printf("80单频调制PM起始相位\n\r");} if(rxd_buf[0]==0x61){rxd_flag=81; printf("81单频调制PM终止相位\n\r");} if(rxd_buf[0]==0x62){rxd_flag=82; printf("82单频调制PM步进相位\n\r");} if(rxd_buf[0]==0x63){rxd_flag=83; printf("83单频调制PM频率\n\r");} if(rxd_buf[0]==0x64){rxd_flag=84; printf("84单频调制PM幅度\n\r");} if(rxd_buf[0]==0x65){rxd_flag=85; stateAM=0;printf("85单频调制PM开启或关闭标志位\n\r"); if(Get_Stat()==0){ Init_ad9910(); statePM=3;ad9910_reset(1); MAS_REST_HIGH; //关闭 } if(Get_Stat()==1){Init_ad9910(); Test(); MAS_REST_LOW; statePM=0;} } //在此直接解算,直接关闭 //单频2FSK if(rxd_buf[0]==0xD1){rxd_flag=86; printf("86单频调制FSK起始频率1\n\r");} if(rxd_buf[0]==0xD2){rxd_flag=87; printf("87单频调制FSK终止频率2\n\r");} if(rxd_buf[0]==0xD3){rxd_flag=88; printf("88单频调制FSK宽度1\n\r");} if(rxd_buf[0]==0xD4){rxd_flag=89; printf("89单频调制FSK宽度2\n\r");} if(rxd_buf[0]==0xD5){rxd_flag=90; printf("90单频调制FSK相位\n\r");} if(rxd_buf[0]==0xD6){rxd_flag=91; printf("91单频调制FSK幅度\n\r"); } if(rxd_buf[0]==0xD7){rxd_flag=92; printf("92单频调制FSK开启或关闭标志位\n\r"); if(Get_Stat()==0){MAS_REST_HIGH; } if(Get_Stat()==1){Init_ad9910(); } } //单频2ASK if(rxd_buf[0]==0x90){rxd_flag=93; printf("93单频调制ASK起始频率1\n\r");} if(rxd_buf[0]==0x91){rxd_flag=94; printf("94单频调制ASK终止频率2\n\r");} if(rxd_buf[0]==0x92){rxd_flag=95; printf("95单频调制ASK宽度1\n\r");} if(rxd_buf[0]==0x93){rxd_flag=96; printf("96单频调制ASK宽度2\n\r");} if(rxd_buf[0]==0x94){rxd_flag=97; printf("97单频调制ASK相位\n\r");} if(rxd_buf[0]==0x95){rxd_flag=98; printf("98单频调制ASK幅度\n\r"); } if(rxd_buf[0]==0x96){rxd_flag=99; printf("99单频调制ASK开启或关闭标志位\n\r"); if(Get_Stat()==0){MAS_REST_HIGH; } if(Get_Stat()==1){Init_ad9910(); } } //单频2PSK if(rxd_buf[0]==0xC0){rxd_flag=100; printf("100单频调制PSK起始相位1\n\r");} if(rxd_buf[0]==0xC1){rxd_flag=101; printf("101单频调制PSK终止相位2\n\r");} if(rxd_buf[0]==0xC2){rxd_flag=102; printf("102单频调制PSK宽度1\n\r");} if(rxd_buf[0]==0xC3){rxd_flag=103; printf("103单频调制PSK宽度2\n\r");} if(rxd_buf[0]==0xC4){rxd_flag=104; printf("104单频调制PSK幅度\n\r");} if(rxd_buf[0]==0xC5){rxd_flag=105; printf("105单频调制PSK频率\n\r"); } if(rxd_buf[0]==0xC6){rxd_flag=106; printf("106单频调制PSK开启或关闭标志位\n\r"); if(Get_Stat()==0){MAS_REST_HIGH; } if(Get_Stat()==1){Init_ad9910(); } } ////其他波形处理函数 if(rxd_buf[0]==0xB5){rxd_flag=107; printf("107\n\r");} if(rxd_buf[0]==0xB6){rxd_flag=108; printf("108\n\r");} if(rxd_buf[0]==0xB7){rxd_flag=109; printf("109\n\r");} if(rxd_buf[0]==0xB8){rxd_flag=110; printf("110\n\r");} if(rxd_buf[0]==0xB9){rxd_flag=111; printf("111\n\r"); if(Get_Stat()==0){MAS_REST_HIGH; } if(Get_Stat()==1){Init_ad9910(); } } recv_state=0; } break; ``` ## 根据不同的标志位,在主函数中节能型相应的操作即可。在主函数中,均是逻辑代码,遵循以下流程: ### 接收到数据-->标志位赋值----根据标志位进行相应的操作 # 整个函数信号发生器的逻辑功能代码大约3000行,相对简单。 # 不在串口中断接收处进行直接逻辑操作,是因为,中断就是要快速相应,遵循快入快出原则。代码执行流程如下图所示。 ![image.png](//image.lceda.cn/pullimage/OEmXTcOg5PGqtWbGSP6EdJ2GR8GWbjzalzBkVjo1.png) # 值得注意的是,HMI传输过来的数据是十六进制,因此需要进行解算为10进制,解算代码如下: ``` uint32_t Get_date(void) { static int val = 0; static uint8_t *pBuf = (uint8_t*)&val; pBuf[0] = rxd_buf[1]; pBuf[1] = rxd_buf[2]; pBuf[2] = rxd_buf[3]; return val; // printf("串口传输过来的频率=%d\n",val); } ``` ## 至于为什么这样请查看数据大小端存储和十六进制转10进制的资料。我也不怎么懂. # 本项目最核心的代码均在AD9910文件夹下,具体请查看上传的代码文件。 ## 波形文件由Matlab生成,需要一定的Matlab基础,波形的生成流程是: ## 1.确实要产生的周期波形. ## 2.对这个周期性波形进行幅度采样,采样点64-1024点,最大值65536(为了刚刚能够存满4096个数组,在数据生成后面加了两个0x00).(跟使用OLED进行汉字取模原理一样,都是把相应的波形数据进行存储到相应数据进行调用). # 调试过程问题 # 在本项目下设计的第一款电路板为红色款,其中的电感封装为1008封装的电感,但是在实际测试过程中发现带不动4.3寸屏幕,后面我给它拆了,换了个大封装6050的22uH的电感,然后就好使了。![微信图片_20240103160857.jpg](//image.lceda.cn/pullimage/wFekBtM4cgd7p0LJgPJpawNtwbSxssOOCKFomiew.jpeg) # 因此在实际电路中,对储能元件的选型还是很重要的AD9910和4.3寸屏幕都是需要较大电流供电,同时还有集成在其中的蜂鸣器,也是需要一点的大电流才能驱动。
设计图
原理图
1 /
PCB
1 /
未生成预览图,请在编辑器重新保存一次
工程视频/附件
序号 文件名称 下载次数
1

文件汇总.zip

217
工程成员
侵权投诉
相关工程
换一批
加载中...
添加到专辑 ×

加载中...

温馨提示 ×

是否需要添加此工程到专辑?

温馨提示
动态内容涉嫌违规
内容:
  • 153 6159 2675

服务时间

周一至周五 9:00~18:00
  • 技术支持

support
  • 开源平台公众号

MP