400Hz高稳信号发生器试验报告

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

A VR单片机实现三相400Hz
高稳信号发生器
一、A VR单片机C语言开发环境
1、A VR单片机C语言编译器
用C语言进行单片机开发,首先要选用一个合适的C语言编译器。

常用的编译器主要有以下几种:
Codevision AVR
这是一个完整的A VR系列的开发系统,有两种版本:完全版支持所有的A VR系列;简单版只支持AT90S系列。

这个软件支持没有SRAM的器件,如Tiny系列的单片机;有限制代码长度的评估版可免费下载,尽管限制了代码长度,但仍能很好的作为评估使用。

Imagecraft C Compiler
简称ICC,是一个完整的A VR集成开发环境,分为两个版本:标准版支持AT90S 系列和Mega系列;专业版有代码压缩功能。

支持没有SRAM的器件的是一个单独的产品ICC-Tiny。

该软件有30天试用版可以下载。

GNU C For AVR
通常称为A VR-GCC,是流行的GNU C编译器在A VR平台上的移植。

可以在多种操作系统,例如MS-DOS、Win32、Linux中使用。

A VR-GCC不是一个集成开发环境,仅是一个C编译器,但是和最新版的A VR Studio 4.12结合可以构成一个简单易用的集成开发环境。

2、A VR单片机C语言集成开发环境
在PC机上推荐使用WinA VR+A VR Studio组合,因为这两个软件都是免费的。

A VR Studio可以从下载。

集成开发环境的建立很简单,下载WinA VR和A VR Studio,分别安装就可以使用了。

最新版的A VR Studio提供了一个动态链接(.DLL),能够自动识别并调用WinA VR编译器。

二、试验方案
1、基本的I/O口实验电路原理图
图1 A VR单片机输入输出结构原理图
2、试验方案的确定
实现400Hz正弦发生器的方法很多,在试验刚开始时选定了三个方案:
7利用AD9850频率合成器,但是由于AD9850的使用十分复杂,因此最早放弃了这个方案;
8利用A VR单片机输出三路数字信号,然后分别利用数模转换输出正弦波,本文最终利用本方法实现;
9利用A VR单片机输出一路数字信号,然后利用模数转换以及相移电路实现三相输出。

3、试验方案
在硬件部分,本文利用了实验室提供的试验板,由于三相输出相对于一相输出而言,仅仅在于相位上的区别,因此对于本试验方案而言,只要能够利用一路实现400
图2 数模转换器接口原理图
图中的5615指TLC5615是一个十位的数模转换器,其写入时序序列如下图所示:
图3 TLC5615时序序列图
这说明,在向TLC5615送数据时,不仅仅要送十位有效数据,而且,我们需要送两个空数(即0)来表示十位数的结束。

图4 数模转换器输入时序图
图5 数字量和模拟电压的关系
上图表明了输出电压和输入数字量之间的关系,本文试验方案最终依据此关系输出。

根据本文的要求,本文应用的芯片是ATMEL mega16L,时钟主频是8MHz,
周期是1.25*10-7s,如果要实现400Hz的输出,周期是2.5*10-3s,因此描一个点所需要的时间是2.5*10-5s。

在设置定时器初值时,由于2.5*10-5s/1.25*10-7s=200,因此使用一个8位定时器就足够,且定时器初值为0xEE。

本文的程序设计时需要计算一个正弦输出表:
时钟频率:8MHz;时钟周期:0.125*10-6s
目标频率:400Hz;目标周期:0.25*10-2s
由于时间周期之间有倍数的关系,因此,本文在试验时,取点也取得是10的倍数点,这样做带来了计算上的方便。

当正弦周期取100个点时:
w=2πfn=0.0628。

当正弦周期取80个点时:
w=2πfn=0.0785。

三、试验程序及结果
利用80个采集点,正弦函数作为初值付值函数,进行波形输出试验,我们得到下图:
图5 输出正弦波1
从这个图我们可以看出一个效果较理想的正弦波形,由于程序指令执行效率的问题,最终的频率只有148.9Hz。

当我们用余弦函数作为初值函数付值时,我们可以得到一个相同的结果:
图5 输出正弦波 2
由于输出点数增多,因此频率减少到只有120Hz左右,但是示波器右下角的显示是240.351Hz,这是由于程序在付值中的错误,在图中顶点处,多输出了一个零点。

因此示波器误将两个最小值点之间的周期作为最小周期,输出了翻倍的频率。

而且在输出时如果对于正弦波取绝对值,那么我们可以得到以下波形:
总结整个试验过程,又两个难点:
1,如何实现C语言条件下的位操作,由于C语言自身没有位操作功能,因此如何在C 条件下实现PORTC的位操作是个难点,本文利用让PORTC分别与$00,$01,$02,$04按位与或的方法来实现;
2,如何尽可能的提高效率,由于程序执行效率的问题,本文输出频率一直无法提高,因此,本文为了解决此问题,做了很多工作,例如,尽量简化程序,由于C 自身的问题,程序简化十分麻烦,因此,本文使用的最多的方法还是减少输出
的点数。

四、存在的问题及未来工作计划
在试验过程中,我发现以下几个问题:
1,GCC的执行效率不高,如果所做的工作需要程序有很高的执行效率的话,我个人建议使用汇编语言,而且汇编语言在程序优化上十分方便。

2,由于试验中所用的DA是TLC5615,这个DA只有一条数据线和单片机相连,因此,他的效率快慢成为系统得瓶颈,从本文所附的程序中可以看出,程
序的绝大部分作用仅仅是将数据向DA送出。

如果能有一个并口的DA,或
者利用通用串行接口,那样,速度会高很多。

3,由于本方法是用DA输出,因此输出电流过小,不利于实际应用;
因此,我对未来的工作提出以下建议:
1,使用汇编语言来编写程序以提高程序的执行效率;
2,使用效率更高的数模转换器件;
3,如果可以的话,可以做后续电压跟随电路,来增强加载负载的能力;
五、试验程序
1,正弦波作为初值函数,80个输出点:
/*系统初始化*/
#include <avr/io.h>
#include <math.h>
#include <stdlib.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <inttypes.h>
/*定义几个初值常量*/
#define pi 3.14
#define a1 0x0001
#define a2 0x0002
#define a3 0x0004
#define a4 0x0008
#define a5 0x0010
#define a6 0x0020
#define a7 0x0040
#define a8 0x0080
#define a9 0x0100
#define a10 0x0200
#define b0 0x00
#define b1 0x01
#define b2 0x02
#define b3 0x04
/*定义正弦函数表*/
int tb[80];
int count=0;
int h,g; /*中间变量*/
/*输出函数*/
void output()
{
if (g!=0)
PORTC=PORTC|b1;
PORTC=PORTC|b2;
PORTC=PORTC&&b0;
}
void main()
{
/*生成正弦函数表*/
unsigned char i;
for(i=0;i<80;i++)
{
tb[i]=(1+sin(0.0785*i))*1000/2;
}
/*IO端口初始化*/
DDRD=0xFF;
DDRB=0xFF;
DDRC=0xFF; /* PC口设置为输出*/ PORTC=0xFF;
PORTB=0xFF;
PORTC=b3;
TCNT0=0xEE;
TCCR0=1;
TIMSK=(1<<TOIE0);
sei();
for(;;){};
}
/*中断处理函数*/
SIGNAL(SIG_OVERFLOW0)
{
TCNT0=0xEE;
PORTC=PORTC&&b0;
h=tb[count];
g=h&a10;
output();
g=h&a9;
output();
g=h&a8;
output();
g=h&a7;
output();
g=h&a6;
output();
g=h&a5;
output();
g=h&a4;
output();
g=h&a3;
output();
g=h&a2;
output();
g=h&a1;
output();
g=0;
output();
g=0;
output();
PORTC=PORTC|b3;
count++;
if (count==79)
count=0;
}
2,余弦函数作为初值函数,80个点/*系统初始化*/
#include <avr/io.h>
#include <math.h>
#include <stdlib.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#define pi 3.14
#define a1 0x0001
#define a2 0x0002
#define a3 0x0004
#define a4 0x0008
#define a5 0x0010
#define a6 0x0020
#define a7 0x0040
#define a8 0x0080
#define a9 0x0100
#define a10 0x0200
#define b0 0x00
#define b1 0x01
#define b2 0x02
#define b3 0x04
/*定义正弦函数表*/
int tb[80];
int count=0;
int h,g; /*中间变量*/
/*输出函数*/
void output()
{
if (g!=0)
PORTC=PORTC|b1;
PORTC=PORTC|b2;
PORTC=PORTC&&b0;
}
void main()
{
unsigned char i;
for(i=0;i<40;i++)
{
tb[i]=((1+cos(0.0785*i))*1023/2);
}
for(i=40;i<80;i++)
{
tb[i]=tb[40-(i%39)];
}
/*IO端口初始化*/
DDRD=0xFF;
DDRB=0xFF;
DDRC=0xFF; /* PC口设置为输出*/ PORTC=0xFF;
PORTB=0xFF;
TCNT0=0xEE;
TCCR0=1;
TIMSK=(1<<TOIE0);
sei();
for(;;){};
}
/*中断处理函数*/
SIGNAL(SIG_OVERFLOW0)
{
TCNT0=0xEE;
PORTC=PORTC&&b0;
h=tb[count];
g=h&a10;
output();
g=h&a9;
output();
g=h&a8;
output();
g=h&a7;
output();
g=h&a6;
output();
g=h&a5;
output();
g=h&a4;
output();
g=h&a3;
output();
g=h&a2;
output();
g=h&a1;
output();
g=0;
output();
g=0;
output();
PORTC=PORTC|b3; count++;
if (count==79) count=0;
}。

相关文档
最新文档