1 [入门必修]按键检测与程序结构...菜菜
//
// MC430F224
// -----------------
// /|\| |
// | | |
// --|RST in1 |--~^~-------|GND KEY1 1
// | in2 |--~^~-------|GND KEY2
// | in3 |--~^~-------|GND KEY3
// | |
// | out1 |------|<|---|Vcc D1 LED
// | out2 |------|<|---|Vcc D2 LED
// | out3 |------|<|---|Vcc D3 LED
//
//************************MC430F224*********************** *********************
#include
//初级用户要习惯采用宏定义,以方便的编写和修改
#define keyio 0xf1 //定义按键IO口,所有键口为0.
#define key_1 0xfd //定义返回键值1
#define key_2 0xfb //定义返回键值2
#define key_3 0xf7 //定义返回键值3
#define LED_D1_flash P1OUT ^= BIT1
#define LED_D2_flash P1OUT ^= BIT2
#define LED_D3_flash P1OUT ^= BIT3
#define bell_delay 7000
//声明子程序
unsigned char key_chcek(void);
void display_update(unsigned char dta);
void key_process_0(void);
void key_process_1(void);
void key_process_2(void);
//********************************************************** ***************
//将单片机初始化程序放在main()前面是方便查看单片机的初始化状态情况.
void MCU_int(void)
{//默认MCLK主时钟频率为DCO=~800K
P1OUT |= BIT1+BIT2+BIT3; //设置LED,上电为灭.电路可以查看MC430F14电路图.
P1DIR |= BIT1+BIT2+BIT3; //P1.1设置为输出.
//MSP430单片机IO口上电默认方向为输入,所以接按键的IO无需再设为输入.
}
//********************************************************** ***************
void main (void)
{ unsigned char key_value; //定义键值全局变是WDTCTL = WDTPW + WDTHOLD; //关狗
MCU_int(); //初始化单片机
while(1) //主程序主循环
{
key_value=key_chcek(); //检测,有键按下并松开,返回一个键值.
switch (key_value) //对键值进行处理.采switch 语法结构查询
case key_1: key_process_0(); //调用键处理程序1
break;
case key_2: key_process_1(); //调用键处理程序2
break;
case key_3: key_process_2(); //调用键处理程序2
break;
default: ; //调用键处理程序4
break;
}
display_update(key_value); //如果有需要可以在这里加上显示更新程序.
key_value=0x00; //最后清除键值.将继续主循环.
}
}
//********************************************************** ***************
//按键检测程序
//返回值: 无符号字符型键值
unsigned char key_chcek(void)
unsigned int i;
unsigned char timp,active;
active=0;
while(!active)
{
while(0xff ==( P2IN | keyio)); //一直等待有键按下
timp = P2IN | keyio; //若有键接下了,则读入IO状态.
for(i=0;i<7000;i++); //延时,是为了去按键抖动.
if (timp ==(P2IN | keyio)) //经延时后,还是那键吗?
{ active = 1; //是,则按键有效.
while(0xff !=( P2IN | keyio)); //一直等待按键松开
}
else
{ //去按键抖动后读入的键值与之前不同.则先效.
active = 0; //再循环检测.
}
}
return timp; //返回一个键值.
}
//********************************************************** ***************
void key_process_0(void) //值处理,用户可以自己修改... {
LED_D1_flash;
}
//********************************************************** ***************
void key_process_1(void) //值处理,用户可以自己修改... {
LED_D2_flash;
}
//********************************************************** ***************
void key_process_2(void) //值处理,用户可以自己修改... {
LED_D3_flash;
}
//********************************************************** ***************
void display_update(unsigned char dta)
{
; //用户可以根据需要来放置显示程序,如LCD,LED,Digital-LED....
//灵活应用,
}
//********************************************************** ***************
2 [入门必修]串行异步通讯例子..菜菜
微控网原创
复制代码
//********************************************************** ******************
//描述:在微控MC430F224开发板上实现UART模块串行异步通讯实验。
//作者:微控技术论坛总版主DC
//编程环境:IAR 3.41
//目标板:MC430F224 (V1.0)
unsigned char BUF; //全局变量,存放
据
//---------------------------------------------------------------------
//关于sign定义
unsigned char sign; //标记寄存器,最大8位标记
#define update sign |= BIT0 //sign位0:置1时,表示有数据更新.
#define check_update sign & BIT0
main( void )
{
WDTCTL =WDTPW+WDTHOLD; //关看门狗
BCSCTL1 =CALBC1_1MHZ; //设定DCO 为1MHZ,
//[0x10FF] TX2振荡器开,高频模式,设定DCO为1MHZ DCOCTL =CALBC1_1MHZ;
volatile unsigned int n;
do //等待晶振稳定{
IFG1 &=~OFIFG;
for(n=5000;n>0;n--);
} while(OFIFG&IFG1);
P1DIR |=BIT1+BIT2+BIT3; //LED--D1,D2,D3
P1OUT &= ~BIT1; //P11 输出0,D1 LED亮
P3SEL |= BIT4+BIT5; //p3.4为TX,P3.5为RX
P3DIR |= BIT4; //P3.4为输出方向(TXD口)
UCA0CTL1 |=UCSSEL0; //[0x40]时钟源选择ACLK=32768晶振
UCA0BR1=0; //设置波特率32768/1200=27.3
UCA0BR0=27;
UCA0MCTL |=UCBRS1; //调整寄存器设置UCBRSx=INT(0.3*8)=2
UCA0CTL1 &=~UCSWRST; //串口状态
机设置完毕,退出USCI设置
IE2 |=UCA0RXIE+UCA0TXIE; //允许收发中断
_EINT();
LPM3; //进入低功耗3并使能总中断
//或写成_BIS_SR(LPM3_bits+GIE);
_NOP();
for(;;)
{ _DINT(); //关闭总中断
_BIS_SR(LPM3_bits+GIE);
}
}
//********************************************************** ******************
//USCI中断用法
//USCI_AX和USCI_BX使用同一个中断向量。接收中断标志UCAxRXIFG和UCBxRXIFG和同
//一个中断向量连接,发送中断标志UCAxTXIFG和UCBxTXIFG 分享另一个中断向量。
//********************************************************** ******************
//接收中断服务程序
#pragma vector =USCIAB0RX_VECTOR
__interrupt void rx_isr(void)
{
BUF = UCA0RXBUF; //接收一个数据后,存入一个全局变量中
P1OUT ^= BIT2; //用D2 LED指示接收到一个数据
update;
LPM3_EXIT; //接收完一个数据后,退出低功耗模式
}
//********************************************************** ******************
//大家注意,MSP340F2上电后UCA0的中断标志寄存器IFG2 中UCA0TXIFG发送中断标志位就置1.
//在初始化时,只要总中断允许了,同时发送中断也允许了.初始化完后,发送中断服务程序就
//被马上执行.
//当UCA0TXBUF空闲时,中断标志寄存器IFG2 中UCA0TXIFG发送中断标志位就置1.
//发送中断服务程序
#pragma vector =USCIAB0TX_VECTOR
__interrupt void tx_isr(void)
{
if(check_update) //是否有数据更新{ UCA0TXBUF = BUF; //是,将接收到的数据发回去
sign &= ~BIT0; //清除标志
P1OUT ^= BIT3; //用D3 LED指示发送完一个数据
}
}
//********************************************************** ******************
3 MSP430F5xxx 在高速公路不停车收费系统(ETC)中的应用
摘要
本文探讨了使用MSP430F5xxx实现ETC系统中实时HDLC编解码的方法。MSP430F5xxx是TI公司MSP430家族最新产品序列,采用先进的0.18工艺,1MIPS消耗的电流低到了惊人的160uA。同时,
F5xx产品都配备了高效灵活的DMA模块,对16bit数据进行搬移只需要2个时钟周期。本文给出了结合F5xx的DMA,TimerA,CRC16及SPI,实现几乎实时的HDLC FM0软解码办法和利用SPI的便捷的FM0编码方法。本文包括相关的两个实例代码。
MSP430介绍
TI公司的MSP430 单片机产品系列具备16-bit RSIC架构,超低功耗。作为MSP430最新产品序列,F5xxx首次采用0.18um工艺,1MIPs 消耗的电流低到了惊人的160uA,主频达到25MIPs 。同时,MSP430F5xxx提供了丰富的片上功能模块,例如,硬件的RTC,12-bit ADC,灵活的时钟系统,硬件CRC16,电源管理模块和多通道的灵活强大的DMA,支持待机模式下的数据交换。
高速公路不停车收费系统(ETC)介绍
不停车收费系统(又称电子收费系统Electronic Toll Collection System,简称ETC系统)是利用RFID技术,实现车辆不停车自动收费的智能交通子系统。该系统通过路侧单元RSU(Road Side Unit)与车载电子标签之间OBU(On Board Unit)的专用短程通信,在不需要司机停车和收费人员操作的情况下,自动完成收费处理过程。ETC车载单元结构
图 1. ETC OBU结构图
如图一所示,OBU由电池系统,MCU,射频,显示和读卡部分(ESAM 卡,CPU卡,射频卡)组成。MCU作为整个系统的中心,负责管理显示,读卡以及与射频部分的数据处理及交换。
FM0编码方式介绍
在车辆通过收费站时,OBU和RSU通过5.8G的载波调制,进行高速的数据交换。数据采用HDLC FM0调制。FM0编码遵循以下三个规则:
A.一个周期内有电平跳变表示”0”;
B.一个周期内没有电平跳变表示”1”;
C.相邻两个周期电平相反。
数据形式请参考图2
图 2. FM0编码方式
车载电子标签(OBU)对MCU的挑战
车载电子标签系统对MCU有两个挑战。一是低功耗;二是高速数据通信能力。
车载电子标签的电池要求有5年以上寿命或者能够支持1万次以上交易。整个系统的低功耗设计成为工程师们的首要任务。其次,RSU
对OBU下行数据波特率达到了256Kbps,上行数据波特率512Kbps。由于车辆通行时间非常短,需要OBU对RSU的数据和命令快速响应。而数据包最长能够达到1Kbits,不允许OBU收下整个数据包之后再解码,这要求MCU有实时编解码的能力。
一般情况下,对FM0的软解码需要得到数据的电平宽度,从而实现解码。通常有两种方式,一种是Timer捕获数据沿,然后软件在中断中判断数据沿之间的宽度。另外一种是定时采样数据口线的电平,通过计数方式得到电平宽度。ETC下行数据速率达到256Kbps,对数据“0”来讲,数据跳变沿之间的宽度只有2uS。对数据“1”来讲,数据沿宽度只有4uS。以第一种方式为例,传统的软解码方式过程如下:
图 3. Timer 捕获中断方式
如图2所示,数据接收过程中,Timer会每2uS或者4uS捕获到一个数据沿,并把数据沿保存到对应寄存器。所以,Timer捕获寄存器里的数据会最快每2uS更新一次。这就需要CPU速度足够快,能够在至少2uS之内完成解码过程。否则,Timer捕获寄存器的数据就会被新的数据覆盖掉,造成解码错误。假设MCU完成1个bit解码的时间需要50个cycle,那么至少需要MCU主频达到25MIPS以上才能实现实时解码。通常,我们会选取主频超过40MIPs的MCU,而这些高速MCU功耗往往难以满足ETC系统的要求。所以,很多ETC 生产商采用双MCU的方式,由一颗高速MCU实现FM0实时编解
码,另外还有一颗低功耗MCU,通常是MSP430来管理整个系统的功耗。这增加了系统的成本和复杂度。MSP430F5xxx的问世,能够同时满足ETC系统对MCU所有的挑战,解决了客户的困扰。
用F5xxx 片上DMA和TimerA捕获功能实现FM0实时解码的方法
MSP430F5xxx卓越的低功耗特性能够满足ETC OBU的低功耗要求。作为MSP430最新产品序列,F5xxx首次采用0.18um工艺,1MIPs 消耗的电流低到了惊人的160uA,片上PMM(电源管理模块)让用户能够根据MCU负荷灵活调节核电压,确保功耗最低。另外,具备多种低功耗状态。在典型的LPM3模式下,打开RTC,RAM数据保持的情况下功耗仅为2uA。
除了卓越的低功耗特性外,MSP430F5xx主频虽然最高只能达到25MIPS,但由于有灵活的多通道DMA,能够与Timer联动,实现数据的自动搬移而不干扰到CPU,这极大的增强了MCU的数据吞吐能力,使主频不再成为瓶颈,而完成对FM0近乎实时的解码。另外,硬件的CRC16模块让MCU只需要操作寄存器就可以完成数据校验。利用DMA和CRC16的实时解码过程如图4所示:
图 4. DMA自动数据搬移的解码方式
数据接收过程中,Timer每2uS或者4uS捕获到一个数据沿,这时会自动触发DMA,DMA自动将Timer寄存器的数据搬移到RAM 区的指定数组当中。整个数据接收过程不需要CPU的参与。有了
DMA的存在,CPU就不需要频繁的进出中断去取数据,也不用担心Timer捕获寄存器数据的丢失,只需专注于解码过程。
图 5. FM0 DMA方式解码图示
解码过程说明:
1. 待机状态:TimerA配置成捕获模式,使能TimerA中断,等待数据到来
2. 捕获到第一个数据沿:在TimerA中断中使能DMA,使能TimerB 及TimerB中断
3. 数据接收:DMA自动将后续的数据沿搬移到内存数组中;同时MCU解码
4. 数据结束:TimerB判断数据接收结束
5. 解码结束
图 6. 程序流程图
实测结果:
采用120bytes的数据做FM0解码测试,其中数据位”1”和“0”约各占50%。MSP430F5438完成解码后,通过串口输出数据如图7所示:
图7. 串口接收到的数据
对上图1Kbits数据,实测MCU完成解码,滞后数据包接收完毕约220uS.如图8所示
图8. 解码实时性
使用MSP430F5xx SPI及DMA实现FM0编码及发送的办法
ETC OBU系统MCU上行数据率是512Kbps。通过灵活应用片上DMA及SPI模块,可以方便的完成FM0数据发送
4 RGB LED 气氛灯光照明——营造温馨照明的MSP430
作者:Dirk Gehrke 和Christian Hernitschek,德州仪器(TI) https://www.sodocs.net/doc/8611955520.html,
高亮度LED 在照明应用中的使用越来越广泛。我们在这里将介绍一种简单的“气氛照明灯”,其仅使用了少量的组件。所有这三种LED 均由使用开关调节器的恒定电流来供电,同时亮度控制由能够产生三种PWM 信号的MSP430 微控制器来完成。可以用磨砂玻璃外壳将印刷电路板安装到台灯中,或者也可以和LED 聚光灯一起使用来进行间接照明。
无论其功耗有多大,现在的LED 通常都使用一个恒定电流源来驱动。这是因为以流明(lm) 为单位的光输出量和电流量成正比例关系。
因此,所有的LED 厂商都规定了诸如光输出(有时称为光学效率)、可视角度和波长等参数,作为正向电流IF 的函数,而非像人们所期望的那样作为正向电压VF 的函数。所以,我们在电路中使用了适当的恒定电流调节器。
用于高亮度LED 的恒定电流
市场上大多数开关调节器都被配置为恒定电压源,而非恒定电流源。将恒定电压调节器转换为恒定电流运行必须要对电路进行简单、稍微的改动。我们使用了一个压降被调节了的电流感应电阻器,而非通常用于设定输出电压的分压器。图 1 显示了该电路的简化图。
图 1 一个开关调节器既可以被配置为一个电压源也可被配置为一个电流源
LED 亮度调节
LED 亮度调节的方法主要有两种。第一种也是最为简单的一种方法便是利用模拟控制直接控制流经LED 的电流:通过降低流经LED 的电流带来降低其亮度。然而不幸的是,这种方法存在两个严重的缺点。首先,LED 的亮度并非严格地和电流成正比例关系,其次,当电流的变化超过LED 额定值时发光的波长(以及由此带来的颜色变化)可能会随着电流变化而发生变化。这两种现象通常是我们不希望看到的。
稍微复杂一点的控制方法是使用能够提供LED 额定工作电流的恒定电流源。这样,附加电路就可以利用给定脉冲间隔比(mark -space ratio) 快速地将LED 开启和关闭,从而平均发出更少的光,感觉就像是光的强度降低了。通过脉冲间隔比,我们可以较轻松地对LED 的感知亮度进行调节。这种方法被称为脉宽调制(或PWM)。
利用PWM 进行调光
作为一个示例,我们将会看到一些使用TPS62260 实施PWM 控制的方法。TPS62260 是一款同步降压转换器,其具有集成的开关元件,典型的时钟频率为 2.25MHz。在图 2 的电路中,我们以黑色显示了将PWM 信号直接连接至EN(使能)引脚的可能性。整个开关调节器电路和PWM 信号一起开启和关闭。在我们实验中的试验表明,在这种配置中,我们可以使用一个高达100Hz 的PWM 频率。这种排列的优点是其简易性:不需要额外的组件。另外,它还是最为高效能的实施方法,因为该开关调节器在关闭时仅产生非常少的静态电流。其缺点是,LED 对使能引脚上高电平的反应被延迟。这是因为开关调节器具有一种“软启动”功能:当器件被开启时,输出电流逐渐上升,直到其达到额定的LED 电流。在一些应用中,这种上升斜坡可能会存在一些问题,因为LED 发光的波长随电流从其最小值到正常工作电平的逐渐增强而变化。例如,在一个DLP 投影仪或LCD 电视面板的LED 背光灯中,这种变化可能是我们无法接受的。但是,就这个示范项目而言,肉眼无法看到这种影响。