找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 14377|回复: 11
收起左侧

自学分析MSP430流水灯程序,不知对错,欢迎拍砖!

[复制链接]
ID:65446 发表于 2014-9-2 15:54 | 显示全部楼层 |阅读模式
本帖最后由 yyjjwan1627 于 2014-9-2 16:13 编辑

1,首先上程序,因为这个程序百度上都有,但是一些细节自己始终弄不懂,闲下来的时候查一查,说实话,没学过C呀,也费了点劲,下面是我自己分析的,不知道对不对,呵呵,
************************************************/  
#include  <msp430x14x.h>   
typedef unsigned int  uint;  
uint i = 0,j = 0,dir = 0;  
uint flag = 0,speed = 0;  //flag--灯光流动方式,speed--灯光流动速度   



***********************************************************************************
void main(void)  
{  

WDTCTL = WDTPW + WDTHOLD;       //关闭看门狗   
    P6DIR |= BIT2;P6OUT |= BIT2;    //关闭电平转换   
    P5OUT &= ~BIT7;  

    CCTL0 = CCIE;                   //使能CCR0中断   
    CCR0 = 50000;  
    TACTL = TASSEL_2 + ID_3 + MC_1; //定时器A的时钟源选择SMCLK,8分频增计数模式   
    P2DIR = 0xff;                   //设置P2口方向为输出   
    P2OUT = 0xff;  

    _EINT();                        //使能全局中断   
    LPM0;                           //CPU进入LPM0模式各时钟全部工作   
}  

我从进入中断程序开始分析吧,

#pragma vector = TIMERA0_VECTOR        
__interrupt void Timer_A (void)   
{   
    if(flag == 0)    ********************************************************************************************************************
//首先flag被赋值为0了,所以IF表达式中(0==0),所以表达式成立了,这flag是无符号的整数,不是位,所以它要执行下面的语句
********************************************************************************************************************
    {  
        P2OUT = ~(0x80>>(i++));    //灯的点亮顺序D8 -> D1   ********************************************************************************************************************
//此语句,拆开分析 :0x80>>(i++), “i++”这是先拿来运用再计算,“i”开始被赋值为0,“>>”表示把“0X80右移多少位,第一次执行把”0x80==10000000“往右移动0 位    “~”此表示取反,则把“100000000”取反得"01111111"表示最高位输出低电平,下一 周期if表达式还是成立的,则把“10000000”右移动1位,这一周期i==1了,这时再取 反得到“10111111”第6位输出低电平,低次输出低电平,这时下面的i累加到7位  j++;也是每一周期加1,当if(flag==0)时,不执行,“else if”和“else”的语句
********************************************************************************************************************                                                                                    
   }  
    else if(flag == 1)  
    {  
        P2OUT = ~(0x01<<(i++));    //灯的点亮顺序D1 -> D8                                 
********************************************************************************************************************
此语句表达式是flag==1时,才会执行,当下面的“j++;“j等于10的  时候,if表达式条件满足,则要执行下面的语句,i,j 被赋值为0,而 flag加               1 以后等于1了,上面定义初始值赋为0,当flag==1时,满足表达式,与  上面不同的是,低电平的输出是从第0位到第8位输出
********************************************************************************************************************
    }  
    else                                                                                                
********************************************************************************************************************
//当“if”,"else if"表达式都不成立时,则要执行else下面的语句,下面使用的是“if    else”套用。
********************************************************************************************************************
    {  
        if(dir)                  //灯的点亮顺序  D8 -> D1,D1 -> D8,循环绕圈  
********************************************************************************************************************  //当if(dir)中,dir为非0时,执行下面的语句,如果为0时,则要执行"else"的语句, dir初始值被赋值为0了,当 D8->D1时,i==8时,i被赋值为0,还有DIR被  取反 ,就是dir开始是0,现在是1,当D1 ->D8时,i==8时,i再次被赋值为0,dir取反以后是0了, dir的来回取反,决定了  D8 -> D1,D1 -> D8,循环绕圈。个  人感觉应该是从D1 到D8,D8再到D1,不知对否?      
********************************************************************************************************************   
        {  
            P2OUT = ~(0x80>>(i++));                                             
        }  
        else  
        {  
            P2OUT = ~(0x01<<(i++));  
        }  
    }  

    if(i == 8)                                                                              
********************************************************************************************************************
//这是当i==8时,则要执行,i被赋值为0,dir 的取反,              
********************************************************************************************************************
    {  
        i = 0;  
        dir = ~dir;  
    }  

    j++;                                                                                ********************************************************************************************************************
//初始值被赋值为0,每次周期运算完以后+1,直到J==10时,
********************************************************************************************************************
    if(j == 10)           
********************************************************************************************************************
  //当J==10时,执行   "i"   "j" 被赋值为0,flag等于1,
********************************************************************************************************************
    {  
        i = 0;  
        j = 0;  
        flag++;  
        if(flag == 4) flag = 0;         
********************************************************************************************************************  //到这if表达式当中又套用“switch   case  (break)”,先看表达式,当 flag == 4 时,flag被赋   为0了,在这之前,“switch  case ”并不工作,因为If表达式没有成立,时钟是用的上面的主  程序SMCLK,并没有分频时的时钟源。
********************************************************************************************************************
        switch(speed)//根据speed的值来选择相应的速度,速度的选择主要通过改变分频来实现   
        {  
        case 0:  
            TACTL &=~ (ID0 + ID1);//这个地方其实没必要,意思是清零TACTL的78两位   
            //ID1的值是0x0080   ID2的值是0x0040通过计算就可以得出   
            TACTL |= ID_3;//改为八分频   
            break;  
        case 1:  
            TACTL &=~ (ID0 + ID1);  
            TACTL |= ID_2;  
            break;  
        case 2:  
            TACTL &=~ (ID0 + ID1);  
            TACTL |= ID_1;  
            break;  
        case 3:  
            TACTL &=~ (ID0 + ID1);  
            TACTL |= ID_0;  
            break;  
        default:  
            break;  
        }  
        if(flag != 3)   speed++;           
********************************************************************************************************************//每三种方式都走完时,才会到下面的IF程序这儿。当 flag==0时,不等于3,所以发speed加1等于1,从第一种Case 1:开始分频作为流 动速。  break,跳出SWITCH
********************************************************************************************************************
        if(speed == 4) speed = 0;                                                      
********************************************************************************************************************
//当speed ==4时, speed被赋值为了,这时从第Case  0:开始分频作为流动速度。 break,跳出SWITCH
    }                                                                                                  
}  


总结:要想学好单片机,还是要熟悉C语言呀,里面全是一些命令语句,控制语句,嵌套语句,哎,头痛呀,再有一个,我感觉这个程序理解上不易,是           不是可以把程序简化,作延时函数还好理解一点。水平有限,都是自己摸索的,不知道对不对,不对的给指证一下。




评分

参与人数 2威望 +12 黑币 +12 收起 理由
piqiu + 5 + 5 赞一个!
daliu + 7 + 7 很给力!

查看全部评分

回复

使用道具 举报

ID:65608 发表于 2014-9-2 16:01 | 显示全部楼层
楼主发的程序对我等msp430的初学者很有用 先收藏 理解一下
回复

使用道具 举报

ID:51089 发表于 2014-9-2 16:03 | 显示全部楼层
楼主的分析完全正确 给详细  太给力了  先谢楼主
回复

使用道具 举报

ID:65446 发表于 2014-9-2 16:05 | 显示全部楼层
谢谢,初次写看了单片机有8天左右了,有不对的欢迎指正!
回复

使用道具 举报

ID:1 发表于 2014-9-2 18:38 来自手机 | 显示全部楼层
我刚才详细看了一下,你的分析基本上是正确的,还没有找到有错误的地方,谢谢分享这对初学者很有用
回复

使用道具 举报

ID:1 发表于 2014-9-2 18:41 来自手机 | 显示全部楼层
不过,在一般的情况下,不建议写这么长的中断函数,中断函数应该尽量减短,改变一些标志位就可以了,然后在主程序里面判断
回复

使用道具 举报

ID:65446 发表于 2014-9-2 20:31 | 显示全部楼层
admin 发表于 2014-9-2 18:41
不过,在一般的情况下,不建议写这么长的中断函数,中断函数应该尽量减短,改变一些标志位就可以了,然后在 ...

好的,以后要注意。这是一个官方的程序,我对着这个官方的程序一点点的查资料弄清楚是怎么回事,还没有编写的经验,以后会多学习的,
回复

使用道具 举报

ID:66032 发表于 2014-9-11 14:05 | 显示全部楼层
你用的是一个I/O Port, 为什么不用数组,根据数组编排这样可以组合几十种流水灯,在中断内执行冗长的函数是不可取的
回复

使用道具 举报

ID:81990 发表于 2015-6-4 09:54 | 显示全部楼层
不过,在一般的情况下,不建议写这么长的中断函数,中断函数应该尽量减短,改变一些标志位就可以了,然后在主程序里面判断
回复

使用道具 举报

ID:92785 发表于 2015-10-18 00:58 | 显示全部楼层
谢谢楼主的程序了
回复

使用道具 举报

ID:65226 发表于 2015-11-7 06:27 来自手机 | 显示全部楼层
谢谢楼主分享  先收藏了
回复

使用道具 举报

ID:1014643 发表于 2022-3-31 16:48 | 显示全部楼层
赶紧学习一波
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表