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

一、实物展示及部分制造流程展示:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

嘉立创开源社区开源连接:基于CW32的多功能函数信号发生器设计

实物展示链接:演示视频

二、详细功能说明

本设计以CW32F030系列单片机为系统控制核心,以AD9910模块作为波形生成系统,HMI4.3寸触摸屏作为人机交互接口,用于设定相关参数,W25Q64作为数据存储设备,以简单的外围电路结构,设计一款多功能函数信号发生器,基本功能GUI界面如图所示。

在这里插入图片描述

项目基本功能包含:

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界面如下图所示.

在这里插入图片描述

2. 三角波输出模式:在三角波模式下,频率、宽度可调,频率步进1Hz,最大244KHz,在三角波输出模式下提供两种波形输出模式.

1.连续双向扫描:播放完一个波形后,波形倒放.

2.连续循环扫描:连续播放一个波形

GUI界面如图所示

在这里插入图片描述

3.方波输出模式:在方波输出模式下波形宽度、频率可调,宽度步进5%,频率步进1Hz。

GUI界面如图所示

在这里插入图片描述

4.其他波形输出模式:输出波形有以下14种常见的波形进行选择:

(1)斩波.

(2)全波.

(3)半波.

(4)对数.

(5)削顶正弦.

(6)辛格函数.

(7)衰减震荡.

(8)削顶三角.

(9)正指数.

(10)负指数.

(11)正阶梯.

(12)负阶梯.

(13)洛伦兹.

(14)高斯.

选择GUI界面如图所示

在这里插入图片描述

在此模式下,波形频率可调,波形输出模式可调。提供两种波形输出模式

1.连续双向扫描

2.连续循环扫描

对应波形输出界面如图所示

在这里插入图片描述

通过点击输出波形按钮,可按照顺序切换1种波形输出。

通过点击确认可进行波形输出,在确认点击按键按下后,再次按下可变为取消按键,取消波形输出.返回按键按下,返回上一级菜单.

4.单频调制GUI如下图所示

在这里插入图片描述

4.单频调制模式下提供

(1)FM调制:

界面GUI如下图所示

在这里插入图片描述

在此模式下可设定FM调制的以下参数:

1.起始频率.

2.终止频率.

3.步进频率.

4.波形幅度.

5.波形相位.

(2)AM调制

GUI如下图所示

在这里插入图片描述

在此模式下可设定AM调制的以下参数:

1.起始幅度.

2.终止幅度.

3.步进幅度.

4.波形频率.

5.波形相位.

(3)PM调制

GUI如下图所示

在这里插入图片描述

在此模式下可设定PM调制的以下参数:

1.起始相位.

2.终止相位.

3.步进相位.

4.波形频率.

5.波形幅度.

(4)2FSK调制

GUI如下图所示

在这里插入图片描述

在此模式下可设定2FSK调制的以下参数:

1.起始频率.

2.终止频率.

3.起始频率持续时间.

4.起始频率持续时间.

5.波形幅度.

5.波形相位.

(5)2ASK调制

GUI如下图所示

在这里插入图片描述

在此模式下可设定2ASK调制的:

1.起始幅度.

2.终止幅度.

3.起始幅度持续时间.

4.起始幅度持续时间.

5.波形频率.

5.波形相位.

(5)2PSK调制

GUI如下图所示

在这里插入图片描述

在此模式下可设定2PSK调制的以下参数:

1.起始相位.

2.终止相位.

3.起始相位持续时间.

4.起始相位持续时间.

5.波形频率.

5.波形幅度.

4.扫描模式下GUI如下图所示

在这里插入图片描述

扫描模式下功能1:扫频

扫频功能下三种不同扫频模式GUI如下图所示

上扫频GUI

在这里插入图片描述

下扫频GUI

在这里插入图片描述

上下扫频GUI

在这里插入图片描述

在扫频模式下可以设定以下参数用于扫频控制:

1.扫频上限频率

2.扫频下限频率

3.扫频步进频率

4.扫频幅度

5.扫频相位

6.扫频时间间隔

7.扫频DRC引脚时间间隔

8.扫频下限频率

9.选择扫频方式:上扫频、下扫频、上下扫频

在扫幅模式下可以设定以下参数用于扫幅控制:

1.扫幅上限幅度

2.扫幅下限幅度

3.扫幅步进幅度

4.扫幅频率

5.扫幅相位

6.扫幅时间间隔

7.扫幅DRC引脚时间间隔

9.选择扫幅方式:上扫幅、下扫幅、上下扫幅

扫描模式下功能3:扫相

在扫相模式下可以设定以下参数用于扫相控制:

1.扫相上限幅度

2.扫相下限幅度

3.扫相步进幅度

4.扫幅频率

5.扫相相位

6.扫相时间间隔

7.扫相DRC引脚时间间隔

9.选择扫相方式:上扫相、下扫相、上下扫相

谐坡调制功能

谐坡调制GUI如下图所示:

在这里插入图片描述

谐波调制功能1: FM调制

谐波FM调制GUI如下图所示:

在这里插入图片描述

在此模式下可设定以下参数用于FM调制

1.FM调制起始频率

2.FM调制终止频率

3.FM调制幅度

4.FM调制相位

5.FM调制斜率维持时间

谐波调制功能2: AM调制

谐波AM调制GUI如下图所示:

在这里插入图片描述

在此模式下可设定以下参数用于AM调制

1.AM调制起始幅度

2.AM调制终止幅度

3.AM调制频率

4.AM调制相位

5.AM调制斜率维持时间

谐波调制功能3: PM调制

谐波AM调制GUI如下图所示:

在这里插入图片描述

在此模式下可设定以下参数用于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进行系统供电。流程图图下图所示。

在这里插入图片描述

电路结构如下图所示

在这里插入图片描述

电源流向:从左向右

在电路结构中存在这些屏蔽掉所有接口的电路,是用于定位孔绘制和3D模型绘制,在实际电路中无任何电气意义。

在这里插入图片描述

对于AD9910的电路,请参考我的其他开源项目进行的详细说明,在本项目中不进行过多论述。

本项目的原理图很简单,复杂的只有供电电路。

PCB设计说明

在本项目下只有两款PCB,第一款是核心板,第二款是AD9910接口的转接板,将2.54mm的排针接口转为PFC接口,用于跟核心板上的FPC接口进行连接,构成一个集成化的系统,避免通过线束的连接方式,在该PCB上开出一个开口,用于将FPC排线引出。

在这里插入图片描述

为降低板子的实际高度,该板尽量薄,因此我打板的时候选择厚度为1.2mm.

通过镂空区域和底部的螺丝柱,可以将AD9910完美的固定在上面。从节省成本上考虑,该部分可以舍去不用,只用底层的螺丝柱即可达到固定效果。板子大于10x10mm,不能使用免费打扮,双层板打板要40多!

在这里插入图片描述

三、设计软件说明

软件部分是整个设计的终点,在硬件电路设计时,一个小下午,硬件电路设计时用了一个多月,涉及的内容比较多。软件运行流程如下图所示。

在这里插入图片描述

4.3寸HMI串口屏代码编写.

串口通信代码流程如下图所示

在这里插入图片描述

串口屏运行流程如下图所示,所有逻辑代码均遵循以下原则

在这里插入图片描述

受限于CW32的片内资源,无法应用一些功能强大的RGB屏幕,因此选用MHI串口屏进行人机交互,实验结果表明,人机交互状态良好,基本实现预定功能。

其中HMI串口屏只用于发送预定帧结构的数据,单片机进行解算后进行相应,单片机不对HMI串口屏进行其他控制。

串口屏帧结构如下图所示:

在这里插入图片描述

帧结构构成:帧头+4位控制数据+帧尾(0A+数据位或标志位1+数据位或标志位2+数据位或标志位3+数据位或标志位3+帧尾)

帧头:0A,数据接收允许标志

数据:屏幕上设定参数构成,最大4个位

帧尾:A0,数据接收结束标志位

如发送一个频率参数,其HMI发送的帧结构为:0A EF 1A 03 06 A0,单片机进行接收,控制系统响应流程如下图所示。

在这里插入图片描述

具体逻辑代码请查看上传的HMI工程,该模块很好上手,在对其进行编程时,我只会画火柴人,UI界面不怎么好看,但是代码逻辑很完善。

在液晶显示部分,你可以理解为你要发什么数据、什么时候发、发了之后怎么样!

2.W25Q64代码编写

在本项目中,还是CW32片内Flash的问题,我只能用W25Q64进行波形数据存储,在CW32下只能定义一个4096大小的数据,因此智能一此次的往对应的4K字节扇区写入4096个波形数据。

在使用W25Q64时应明确:

1.你要把数据存到(128块每块64)块中的哪一块。哪一块的那个扇区(32K),哪个扇区的那个区域(4K),那个区域的那个页(256字节)的地址。

本项目存储数据都是线性存储,都是4096个数据,相当于一次寸一个区域,一个32K的扇区可以寸8个波形,一个64K的块可以存16个波形,因此需要大约3个快进行数据存储。存入结构路程如下图所示。

在这里插入图片描述

波形写入步骤如下图所示

在这里插入图片描述

1.波形数据存入4096大小的数组:const uint8_t Wave_Date[4096]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.选择写入的4K扇区,用十进制数表示,从0开始向上递增

在这里插入图片描述

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行,相对简单。

不在串口中断接收处进行直接逻辑操作,是因为,中断就是要快速相应,遵循快入快出原则。代码执行流程如下图所示。

在这里插入图片描述

值得注意的是,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的电感,然后就好使了。

因此在实际电路中,对储能元件的选型还是很重要的AD9910和4.3寸屏幕都是需要较大电流供电,同时还有集成在其中的蜂鸣器,也是需要一点的大电流才能驱动。

若有疑问请查看立创开源社区工程!

  • 20
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值