C6437通过串口通信生成指定波形、幅值、频率、相位的梯形波
综述
C6437生成梯形波,可以用C语言进行分段式的编程形成梯形波。
难点在于串口通信采用的是字符串,需要进行字符串和整数型的转换和定标数据。由于采用数据定标,输入的部分都是整数型,所以不考虑浮点数,如果有输入浮点数,则在字符串和浮点数转换过程要再加一步。
头文件部分
#include "math.h"
#include "stdio.h"
#include "evmdm6437.h"
#include "evmdm6437_uart.h"
定义数值
#define NX 1024
float temp[1024],txb[1024],c[1024];//temp临时数组,txb梯形波,c谐波
Int16 tmp,i,j,k,t,len,n;//i,j是用来计数的,t是时间,len是长度。
//k是用来给字符型浮点数计算的,计算完后k清0,再用来判断波形的正负周期。
float p;//相位
float f;//频率
float v;//幅值
float q;//谐波
float pi=3.14;
char rx[256];
int Q;//定标
主函数
void main(void) //第一个void无返回,第二个(void)空参数
{
UART_Handle uart1;
/* Initialize BSL */
EVMDM6437_init();//函数,功能为初始化dm6437
*(Uint32 *)0x01c40004 = 0x200000;//对32位内存映射寄存器进行操作,初始化0x01c40004地址中的值为0x200000
/* Open Uart Handle */
uart1 = SEEDDEC6437_UART_open(1,
baud_9k6,//波特率
data_w8,//每个字节有8位
data_s1,//1个停止位
data_p);//奇偶校验位
/* Setup buffers */
for (i = 0; i < 0x100; i++)//给rx数组清零
{
rx[i] = 0;
}
while(1)
{
i=0;
while(1)
{
while (1)
{
tmp = EVMDM6437_UART_rcvReady(uart1);//串口准备接受数据
if (tmp == 1)//如果接收到数据,则tmp为1,跳出循环
break;
}
EVMDM6437_UART_getChar(uart1, &rx[i]);//读取字符型数据
while (1)
{
tmp = EVMDM6437_UART_xmtReady(uart1);//中断控制
if (tmp == 1)
break;
}
EVMDM6437_UART_putChar(uart1, rx[i]);//输出rx[i],且如果读到"@"符号就跳出
if (rx[i]=='@')
{
len=i;
break;
}
i++;
}
//输入字符串指令,例如90 50 1 5 @,表示相位为定标值90,频率为定标值50,幅值为定标值1,谐波为定标值5。因为输入的数字都是以空格隔开的,所以可以利用空格来进行每个数据的读取。
printf("依次输入定标后的相位 频率 幅值 谐波 以@结束");
p=0;f=0;v=0;
i=0;
Q=2;//Q2定标
while(rx[i]!=' ')//当数组中的数不是空格的时候,执行运算
{
p=p*10+rx[i]-48;//48为字符0的ASCII码值,即字符型转换为整型
i++;
}//计算相位p
i++;
for( n=0; n < Q; n++)
{
p /= 2;
}
while(rx[i]!=' ')//当数组中的数不是空格的时候,执行运算
{
f=f*10+rx[i]-48;
i++;
}//计算频率f
for( n=0; n < Q; n++)
{
f /= 2;
}
i++;
//计算字符型浮点数:比如输入v=1.2,在小数点之前,v=0*10+49-48=1,在小数点之后,v=1*10+50-48=12,k=1
//明显v变大了10倍,就要除以10,而且如果k=2,则v变大100倍,以此类推
while(rx[i]!=' ')//当数组中的数不是空格的时候,执行运算
{
v=v*10+rx[i]-48;
i++;
}
for( n=0; n < Q; n++)
{
v /= 2;
}
i++;q=0;
while(rx[i]!=' ')
{
q=q*10+rx[i]-48;
i++;
}//计算谐波数
for( n=0; n < Q; n++)
{
q /= 2;
}
printf("%e !\n", q);
i++ ;
//到这里完成了字符型到整型数or浮点型数的转化
t=f/25; //t为NX个点的半周期数 以基波50hz为例,t=2,就有两个半周期组成1024个点的大周期
for (i=0;i<t;i++) //i从0开始,意味着0/2=0 第一个半周期肯定是正的
{
if (i%2==0) //i被2整除
{
k=1;
}
else k=-1; //确定波形的正负
for (j=NX*i/t;j<NX*(i+1)/t;j++)//在半个周期里,比如f=50时,t=2。i=0时,j=0到j=512,i=1时,j=512到1023
{
if ((j >= NX*i/t) && (j <= NX*i/t+NX/4/t))//&&逻辑与,&位与。t=2,i=0时。0<=j<=128
{
temp[j] = 4*k*v*((j*t/1.0/NX-i));
}
else if ((j>NX*i/t+NX/4/t) && (j <= NX*i/t+NX*3/4/t))//t=2,i=0时。128<=j<=384
{
temp[j] = k*v;
}
else
{
temp[j] = 4*k*v*((i+1-j*t/1.0/NX));//t=2,i=0时。384<=j<=512
}
}
}
for (i=0;i<NX;i++)
{
txb[i]=temp[(i+p*NX/t/180)%NX]; //移相 %是求余数
} //梯形波生成
for (i=0;i<NX;i++)
{
c[i]=16*1.0*v/(pi*pi)*(1/(q*q)*sin(q*pi/4.0)*sin(q*2*pi*f*i/(1024*50)));
}
while (1)
{
tmp = EVMDM6437_UART_xmtReady(uart1);
if (tmp == 1)
break;
}
EVMDM6437_UART_putChar(uart1, '#'); //#程序结束
}
浮点数问题
如果不需要定标,则输入的可能是浮点数,比如输入的幅值为1.5V,则字符串到还原成1.5的过程如下:
//计算字符型浮点数:比如输入v=1.2,在小数点之前,v=0*10+49-48=1,在小数点之后,v=1*10+50-48=12,k=1,明显v变大了10倍,就要除以10,而且如果k=2,则v变大100倍,以此类推。
while(rx[i]!='.')//当数组中的数不是空格的时候,执行运算
{
v=v*10+rx[i]-48;
i++;
}//幅值是浮点数,这里计算的是浮点数的整数部分
i++;
k=0;
while(rx[i]!=' ')
{
v=v*10+rx[i]-48;
i++;
k++;
}//计算浮点数的小数部分
while(k>0)
{
v=v/10.0;
k--;
}//计算幅值v
定标问题
由于不涉及加减乘除等计算,所以程序采用的是统一定标。
这里简要说一下定标Q。
DSP处理器处理浮点数的办法之一是定标,把浮点数转化为整数。
比如Q3定标1.5,那么计算如下:
int(1.5X2^3)=12
那么定标完的数据就是12。