图4-1 发生波形图(f=30HZ) 图4-2 LED点亮图 4-3 LED熄灭图
2)给定信号频率高于50HZ时,LED灯熄灭,并且通过PC机显示信号频率,如图5所示为信号频率为600HZ时,PC机显示结果:
图5 f=600HZ时的频率显示
3、实验中遇到的问题
在实验过程中,出现了不少的问题,首先是AD中断经常需要经过开关实验板来重置,这个问题应该是硬件接触不良的原因引起的;其次,在实验初期,当频率f<50HZ时,经常会出现波形变成噪声的情况,导致不能进行信号周期的计算,如图6所示为f=30HZ的标准正弦波的波形。但是如果f比较大时,不会出现这种情况,将f从大逐渐减小至30HZ,则波形又能正常显示,这个问题我们暂时还未能讨论出可靠的干扰原因。
图6 f=30HZ时的error噪声波形
四、源程序
//头文件
#include \
// DSP2833x Headerfile Include File
#include \
// DSP2833x Examples Include File
#include \interrupt void adc_isr(void); void scib_fifo_init(); //地址定义
volatile unsigned int* p_ceselect=(volatile unsigned int *)0x;
volatile unsigned int* p_trafficaddr=(volatile unsigned int *)0x;
volatile unsigned int* p_ioenable=(volatile unsigned int *) 0x;
//设置A/D采样时钟频率为12.5MHz,宽度为16 #if (CPU_FRQ_150MHZ)
// Default - 150 MHz SYSCLKOUT #define ADC_MODCLK 0x3
//HSPCLK= SYSCLKOUT/2*ADC_MODCLK2
= 150/(2*3) = 25.0 MHz
#endif
#if (CPU_FRQ_100MHZ)
#define ADC_MODCLK 0x2
//HSPCLK= SYSCLKOUT/2*ADC_MODCLK2
= 100/(2*2) = 25.0 MHz
#endif
//定义全局变量 Uint16 LoopCount; Uint16 ConversionCount;
Uint16 Voltage1[1024]; //存储波形采样数据 Uint16 num=0,cj=0,flag=0; //用于频率计算的参数 float32 T,Ts=7.68e-6; //信号、A/D采样周期T、Ts Uint32 f; Uint16 Tjc=0;
//信号频率f=1/T //信号采样周期计数
#define ADC_CKPS 0x1
// ADC module clock=HSPCLK/2*ADC_CKPS
= 25.0MHz/(1*2) = 12.5MHz
#define ADC_SHCLK 0xf
// S/H width in ADC module periods
= 16 ADC clocks
unsigned int iostatus=0; main() {
InitSysCtrl();/ //系统初始化 //GPIO口初始化
InitGpio(); // Skipped for this example InitSciGpio();//设置SCI模块所用到的GPIO口 DINT;
InitXintf();
InitPieCtrl(); // 初始化中断 IER = 0x0000; // 清除中断标志
IFR = 0x0000; // 清除中断标志
*p_ceselect =0x3 ; //打开ce3空间
DELAY_US(100); //延迟函数
*p_ioenable =0xfff; //IO空间始能
DELAY_US(100);
InitPieVectTable(); // I初始化中断向量表 //设置A/D中断入口 EALLOW;
PieVectTable.ADCINT = &adc_isr; EDIS; //初始化SCIB模块和A/D模块 scib_fifo_init(); // Init SCI-B
InitAdc(); // For this example, init the ADC //使能AD中断
PieCtrlRegs.PIEIER1.bit.INTx6 = 1; IER |= M_INT1; // Enable CPU Interrupt 1 EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM LoopCount = 0; ConversionCount = 0; //AD模块初始化
AdcRegs.ADCTRL1.bit.ACQ_PS= ADC_SHCLK;
//采样时间预定标
AdcRegs.ADCTRL3.bit.ADCCLKPS= ADC_CKPS;
//AD时钟预定标
AdcRegs.ADCTRL1.bit.SEQ_CASC=1;
//级联排序
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 0x1;
//中断使能
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 0x1; AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x6;
//将第6通道的转换结果存放在CONV00中
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 15;
//最大转换通道为16
AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 0x1 ;
//软件触发启动
for(;;); // 循环等待AD中断 }
//AD中断函数
interrupt void adc_isr(void) {
Voltage1[ConversionCount]
= AdcRegs.ADCRESULT0 >>4;
//将采样所得数据结果存储到Voltage1数组中 if(Voltage1[ConversionCount]>50)
flag=1; //当采样值大于50时,flag置1
if(num>=1)
cj++;
// num大于1时,cj开始计数
if(flag==1) // flag为1时,如果采样值小于200,
//num计数加1,同时将flag置0;
{ if(Voltage1[ConversionCount]<200) { num++;flag=0;}
}
if(num==2)
//num=2时,计算信号频率,并重置参数
{ num=0; T=cj*Ts; //计算信号周期 f=1/T;
//计算信号频率
cj=0; //信号采样点计数复位 Tjc++;
//信号采样周期计数
}
if(ConversionCount == 1024)
//If 1024 conversions
//have been logged, start over
{
ConversionCount = 0; }
else ConversionCount++;
if(Tjc==0) //每10个信号周期,
//执行一些操作
{
if(f<50)//信号频率小于50Hz时的一些操作
{
iostatus=*p_trafficaddr;
if(iostatus==0)
//判断上一次LED灯的状态
iostatus=0xfff; //点亮LED灯 else
iostatus=0;
//熄灭LED灯
*p_trafficaddr=iostatus;
}
else //信号频率大于或等于50HZ时
{
iostatus = 0;
*p_trafficaddr=iostatus; //熄灭LED灯
//将信号频率传输给上位机,传输格式为:xxxHZ while(ScibRegs.SCIFFTX.bit.TXFFST!= 0);
//SCI端口不空闲,循环等待
ScibRegs.SCITXBUF=f/1000+48;
//信号频率千位转化为字符输出
while(ScibRegs.SCIFFTX.bit.TXFFST != 0); ScibRegs.SCITXBUF=f00/100+48;
//信号频率百位转化为字符输出
while(ScibRegs.SCIFFTX.bit.TXFFST != 0);
ScibRegs.SCITXBUF=f0/10+48;
//信号频率十位转化为字符输出
while(ScibRegs.SCIFFTX.bit.TXFFST != 0);
ScibRegs.SCITXBUF=f+48;
//取信号频率个位转化为字符输出
while(ScibRegs.SCIFFTX.bit.TXFFST != 0);
ScibRegs.SCITXBUF='H'; //输出字符'H'
while(ScibRegs.SCIFFTX.bit.TXFFST != 0); ScibRegs.SCITXBUF='Z'; //输出字符'Z' }
}
//复位AD模块
AdcRegs.ADCTRL2.bit.RST_SEQ1= 1;
// 重置排序器 SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR= 1;
// Clear INT SEQ1 bit
PieCtrlRegs.PIEACK.all=PIEACK_GROUP1;
// Acknowledge interrupt to PIE
AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 0x1 ; return; }
//SCIB模块初始化函数 void scib_fifo_init()
{ ScibRegs.SCICCR.all =0x0007;
// 1位停止位,数据位为8个字节,
//无奇偶校验位,空闲线方式
ScibRegs.SCICTL1.all=0x0003; // 发送、接收使能
ScibRegs.SCICTL2.all =0x0003; ScibRegs.SCICTL2.bit.TXINTENA =1; ScibRegs.SCICTL2.bit.RXBKINTENA =1; ScibRegs.SCIHBAUD=0x0001;
//设置通讯频率为9600
ScibRegs.SCILBAUD=0x00e7; ScibRegs.SCICCR.bit.LOOPBKENA =0;
// Disable loop back
ScibRegs.SCICTL1.all =0x0023;
// Relinquish SCI from Reset
ScibRegs.SCIFFTX.bit.TXFIFOXRESET=0; ScibRegs.SCIFFRX.bit.RXFIFORESET=0; ScibRegs.SCIFFTX.all=0xE040;
ScibRegs.SCIFFRX.all=0x204f; ScibRegs.SCIFFCT.all=0x0; }
五、实验总结
通过本次实验,初步掌握了TMS320F28335扩展数字I/O口的方法及应用,A/D转换模块的性能、数据采集及编程方法,了解了F28335的SCI模块的结构及特点,串行口工作方式及编程方法,PC机串行通讯的工作过程,中断处理程序的编程方法。