该系统的框图如下:
硬件说明:KeyBroad为4X4的矩阵键盘;MCU为TI的MSP430F5529,实验板上自带LCD;DA为单极性的电压输出型TLV5638,在放大之前需要经过一个HPF滤掉直流;sin后面的4阶LPF为巴特沃斯,截止频率15KHz;triangle后面的LPF截止频率为三角波的7倍频左右,但效果不是很理想;同相放大的倍数为7.8倍。
软件说明:该程序的主体是向DA发送DDS的数据,外设主要有矩阵键盘、显示屏、滑轮、按钮。其中的按钮用到端口的中断,不占用MCU时间,只有检测到下降沿即开始动作;另外3个都比较耗时间,矩阵键盘采用翻转2次读取高低4位的方法;显示屏为SPI控制;滑轮为AD转换控制。原本方波是想利用正弦通过比较器输出方波,但是这种方法不能调节幅度,且占空比的调节也不是线性的。后来改为DDS产生方波,占空比的调节是通过建立一个长度为100的占空比数组。
MSP430的中断机制:MSP430的中断优先级按所在的向量的大小排列,中断向量地址越高优先级就越大,但是默认的MSP430是不能中断嵌套的,要想在执行某一中断时能够响应更高优先级的中断,需要在低优先级的中断程序中手动打开全局中断便能位,因为在进入中断服务子程序时全局中断便能位被清零,即禁止响应其它中断。msp430的指令中,_DINT()和_EINT()分别为关和开所有中断,也就是包括P1IE、P2IE、WDTIE、TAIE、TBIE、ADC12IE、串口IE的所有中断允许位为“0”和为“1”。
实现中断嵌套需要注意以下几点:
1)430默认的是关闭中断嵌套的,除非你在一个中断程序中再次开总中断_EINT();
2)当进入中断程序时,只要不在中断中再次开中断,则总中断是关闭的,此时来中断不管是比当前中断的优先级高还是低都不执行;
3)若在中断A中开了总中断,则可以响应后来的中断B(不管B的优先级比A高还是低),B执行完再继续执行A。注意:进入中断B后总中断同样也会关闭,如 果B中断程序执行时需响应中断C,则此时也要开总中断,若不需响应中断,则不用开中断,B执行完后跳出中断程序进入A程序时,总中断会自动打开;
4)若在中断中开了总中断,后来的中断同时有多个,则会按优先级来执行,即中断优先级只有在多个中断同时到来时才起做用!中断服务不执行抢先原则。
5)对于单源中断,只要响应中断,系统硬件自动清中断标志位,对于TA/TB定时器的比较/捕获中断,只要访问TAIV/TBIV,标志位被自动清除;对于多源中断(多个中断源共用一个中断向量)要手动清标志位,比如P1/P2口中断,要手工清除相应的标志(访问P1IV也可清楚标志位),如果在这种中断用"_EINT();"开中断,而在打开中断前没有清标志,就会有相同的中断不断嵌入,而导致堆栈溢出引起复位,所以在这类中断中必须先清标志再打开中断开关。
特别注意:
MSP430中断的优先级与其它CPU的中断的优先级的概念不是一回事。
1、当同时有多个中断来的时候才有优先级。其实这个时候很少发生。
2、有中断响应以后自动关闭总中断。这时,谁也别想再中断了。
3、在中断中打开总中断,谁都可以打扰你。
SPI发送:为保证数据发送的连续性,程序尽量不要使用while等延迟,不要使用while (!(UCB0IFG&UCTXIFG))来发送数据,应该开启SPI发送中断,在采样定时器中断中发送数据并使能SPI中断,当数据发送好后,进入SPI发送中断,在该中断中发送第二个字节,然后失能SPI中断。
显示屏:只有当频率、幅度等参数发生改变时才刷新显示,且不能全屏更新,只覆盖需要更新的部分,平时不刷新显示,保证了平时波形的稳定显示。
滑轮:在主程序中设置一个计数变量i,当i大于某个定值时,才进行滑轮AD转换和矩阵键盘扫描。由于在滑轮不动时,AD转换出来的结果不会稳定在一个值,而是会在某个值上下跳动,我们用两个值标识,new和old,当new和old相差大于一定值时(这里设置为6),才改变滑轮值。
矩阵键盘:高4位输出低电平,低4位设置成上拉输入,读取低4位的值;再将高低4位反转,读取高4位,这样组成的8位码即可确定出具体按键,这里需要注意一个问题:将PORT口设置完成后,需延迟一段时间PORT口才能生效(此处的延时极短,不影响程序的性能)。
(由于TI的例子程序中的按钮和滑轮都用到了LPM低功耗模式,在等待AD转换结束和按键消抖时进入LPM,为了效率,我们将等待LPM删除,按键消抖用15ms的看门狗中断。)