1.代码运行时间
代码运行时间,可以采用多种方式测量,它们之间是吻合的:
Ø 示波器接IO引脚
Ø CPU计数器
Ø 定时器0
Ø EPWM模块
1.1示波器接IO引脚
将GPIO设置为通用IO口,输出模式,在待测试代码之前和之后,置位或者复位或者不断取反,即可在示波器上面读出代码运行时间;
对于一段运行时间不多的代码,示波器可能一出现一下就被覆盖掉了,测试这样的代码有两种方法:
Ø 累计:在代码外面加一个比较大的数循环,从而得到累计时间,再除以这个大数,即得到真实值;
Ø 循环:不断地执行这段代码,从而不断出现高低电平,这样就可以读到数据了;
1.2CPU计数器
菜单栏:Profile——Clock——Enable+View;即可在右下角看到计数器,计数代表的是CPU的计数个数,150MHZ情况下,乘以计数周期6.67ns即可得到真实值!
双击该计数值即可清零!
1.3定时器0
设置完分频数之后,要将周期设置到很大,这样可以避免跨越周期的计数错误,比如如果只设置3000,计数到1000,你无法判断3000*N+2000中的N为多少;如果分频数设置过大,也会造成量化误差过大;
1.4EPWM模块
该模块同样存在定时器0的相似问题,一个增减计数,如果周期时1000,计数到800,就难以判断是在上升沿还是下降沿;一个办法是在此计数值读取之后,执行几句代码再读取一次,就可以求取斜率,从而判断上升下降沿!
其他利用DSP内部模块测量,都与定时器和EPWM模块类似,存在的问题也类似!
2.CMD与MAP文件
2.1内存结构
所有的程序和数据都必须在内存中运行,28335的各种内存如下表所示:
内存类型
容量K
含义
RAM
34
掉电会丢失,速度比FLASH快
FLASH
256
烧写程序和数据使用
ROM
1
很少使用
PF
0-3
数据空间,外设寄存器
PIE
中断向量表
2.2CMD分配
Ø H文件里面,通过结构体和共用体,将外设0-3的相关寄存器全部定义为结构体变量;C文件里面,使用#pragma DATA_SECTION(X,Y)指定这些结构体X分配到内存Y中;然后在CMD中,将外设空间分块,再将Y指定分配到具体物理地址块中:DEV_EMU : origin =0x000880, length = 0x000180 。这就是PF0-3的内存映射;这一部分是不变的,芯片型号一定,这些内容就定了,PIE向量表也是这样分配
Ø 我们可以分配的就是RAM和FLASH,可以通过指定#pragma DATA_SECTION()或者#pragma CODE_SECTION()将指定代码或者数据指定分配到某个地址,如果不指定,就由编译器分配;某些算法要求指定,比如FFT;
Ø 以.reset为特征的,以点开始的是编译后的一些量,比如全局变量,这些可以查资料,自己没怎么关注!
2.3MAP
编译之后,File——Open,在debug里面,可以打开Map文件,李曼包含了编译后的物理内存分配信息:
这一块是代表内存分配,我们将所有的内存划分的小块,包括程序空间0和数据空间1;从左到右分别是:小块的属性(0-程序,1-数据)和名称,起始地址,长度,已经使用的空间,剩余的空间,地址的属性;
这个讲我们分配的段的物理地址,刚才那个是讲物理地址分块,现在这个是映射的意思。
这些是全局变量的地址;map文件就大概由这三类组成。查看map文件,可以看到剩余多少空间,以及空间不够合理的时候的优化等等!
2.4小结
CMD和map就主要管理内存!
3.烧写运行与在线仿真
3.1RAM在线仿真
编译完成之后,直接file——load program进去之后就可以跑了;
它测试的时间会比烧写到flash里面快很多,实际应用都是烧写,所以这种比较好像并没有意义,真正有意义的是下面两种;
3.2FLASH烧写运行
从RAM在线运行到flash烧写运行,需要改的地方:
Ø 主函数里面:使用MemCopy函数将代码运行地址从RAM拷到flash里面;初始化FLASH,比如使能管道,可以提升速度,另外根据最高频率,设置最快翻页和等待时间:
Ø CMD文件中:将指定段分配到具体的物理位置:
Ø 另外,不能再flash内部初始化flash,就是不能自己对自己操作,所以有了CMD文件里面的load出来,同时在源文件里面要对这个块进行指定:
#pragma CODE_SECTION(InitFlash, "ramfuncs");
Ø 总结一下:其实程序真正是到load到ram里面,还是烧写到FLASH里面,是CCS里面点击不同按钮操作来决定的。上述的三个步骤只是保证烧写到flash里面可以正常运行而已:需要初始化flash,但是不能自给初始化自己,所以要将初始化代码,先指定一个段,然后再CMD中将该段设置为烧写后load。同时在主函数里面执行将该段代码复制出来再运行;应该就是这个逻辑!
3.3FLASH烧写、LOAD运行
Ø 与上一节烧写类似,上一节可以将FLASH初始化函数load出来运行,其他的load出来运行的步骤也是一样:指定代码分配;主函数里面复制代码,执行代码;CMD将指定的块分配到具体物理空间;
Ø Load运行主要用于某些对时间要求高的场合,烧写之后,如果load出来,速度大概可以达到百分之八十。应用场合包括,某些中断里面的反复做的控制等
3.4疑问
Ø MemCopy函数中使用到的变量,举例:
MemCopy(&RamfuncsLoadStart,&RamfuncsLoadEnd, &RamfuncsRunStart);
这些变量的定义:
extern Uint16RamfuncsLoadStart;
但是并没有初始化,这一句也不知道是在这里定义还是只是在这里引用。我理解的是它是在编译器内部定义了的,这里只是一个引用申明:x的其实地址就是xLoadStart,以此类推。因为我自己使用的段,也可以这样使用,说明是编译器在管理;
4.外设
4.1ePWM
6路12个PWM,也可以配置为高精度PWM(这个自己没用过)。可用于三电平逆变器的控制,12路既可以对称控制,也可以单独控制;控制单元主要分为七个模块:
时基模块:确定计数周期,计数模式(上、下、上下);
计数比较模块:计数比较寄存器;
动作模块:配置计数比较相匹配的模式(与周期相等,与零相等等),以及动作类型(置位、复位、翻转);
死区模块:产生对称或者独立波形,死区设置;
斩波和错误联防:这两个模块没有使用过;
事件触发模块:计数值等于某个设定值后触发指定动作,可用于触发ADC,从而在中断里面实现采样控制;
4.2eCAP
该模块是复用的:6个既可以用于PWM产生——只能产生独立的PWM,也可以用于捕获上升沿或者下降沿;
4.3ADC
4.3.1采样
Ø 电流采样,主要采用CT进行;电压采样,既可以用PT,也可以用一串电阻串联,从中某个电阻取电压;
Ø 电流采样之后,一般也要经过一个电阻,转化为电压信号,再到后面进行处理
4.3.2调理
Ø 最基本的电压跟随器,解除负载效应;
Ø 使用二极管限幅,因为调理之后就要输入ADC模块,该模块有幅值限制;
Ø 对于交流量,可能会使用一个加法电路,叠加一个直流量,将信号提到ADC接受的范围内;
Ø 使用电容等构成滤波电路,这个截止频率很大,用于稳压,滤掉极高频分量;
4.3.3ADC
Ø 主要看两个指标:转换精度——用转换位数来表示,比如12位代表最大值3V只能转换到4095,如果位数增加,转换精度则增加;转换速度——这个可以配置,自己没有亲自动手配置过;
Ø ADC有多种转换方法,在数字电路里面有详细,但是在DSP里面只需要封装好,不需要去管这些内部细节;
Ø ADC模块可以配置为单独两组8个,也可以级联为一组16个;可配置转换数量,转换储存位置;可触发中断;
Ø 有空可以自己动手写一写这个模块的代码!