这是本人第一次在在本站发表文章,本人只是一枚大一新生(开学即大二),有好多不懂而且模糊的东西,若有疏漏或不正确希望大家及时指正。
由于今年参加电赛,本人带着一点点51基础去学习了msp430系列单片机, 我使用的是msp430 f5529这块板子,入门起来不是很轻松,网上教程也很少(与stm32之类的相比),写这篇文章是为了给像我一样基本零基础的人能比较轻松地学习这样一个16位的单片机。
本人学习过程中也有很多模糊的地方,不清楚的地方我在本文章中简要说明,防止误导大家
msp430系列单片机是一款16位的单片机,51单片机为8位,stm32系列为32位,顾名思义, 位数越高代表着该单片机处理数据的能力越快,性能也就越高。那么32位机器处理性能好,8位机器廉价性价比高,我们为什么要选择一个中间位置的16位单片机呢。它的亮点在于它的超低功耗。
字面意思,超低功耗就是这块板子有一个低功耗模式,进入低功耗模式之后就可以长时间极少耗损地待机,定时唤醒cpu进行工作,在能量来源很少的情况下是很有必要节约能量的。
本单片机是ti公司开发的产品, 所以想要获得其资料的最好地方就是ti官网
,在搜索栏直接搜索产品型号MSP-EXP430F5529LP, 里面有产品的各种资料,超级有用的用户指南(user‘s guide)也在这里,虽然是全英文的,但是只要有点英语水平静下心来慢慢看,会有很大收获的。
用户指南=手把手教你入门本产品
该单片机使用较多的编程环境有IAR和CCS。本人使用的是ccs所以对其进行讲解。
Code Composer Studio (CCS) 可以在官网下载,直接搜索即可。
由于msp430单片机内部集成了仿真器, 所以直接通过usb连接到电脑就可以进行硬件仿真,非常方便。
有一个小问题可能太简单了所以当时遇到的时候并没有搜索到答案:
仿真的同时代码就已经烧录到了板中, 此时板子只要供电,就可以自动执行代码。
目前可以说是准备工作都结束了,可以进行调试了。
以下为本人的学习路线,供大家参考
接下来我会简单概述一下这个几个部分,详细的大家可以看看其他大神的文章,讲的都很详细。
由于本人是从51过度过来,所以会对比51单片机的语法来写一下一部分。
操作模式和51单片机类似,都可以进行位操作,操作相应的GPIO口就能进行相应的控制
我们来看一下下面的代码:
//51的位操作
sbit P10=P1^0;
void main()
{
P1^1 = 1;// P1^1进行拉高
while(P10 == 1); //判断P1^0信号
}
//msp430的位操作
void main()
{
P1DIR |= BIT1;//P1^1 GPIO设置为 OUT模式
P1OUT |= BIT1;// P1^1 进行拉高
P1DIR &=~BIT0;//P1^0 GPIO设置为 IN模式
while(P1IN & BIT0); //判断P1^0信号
}
想要去给我们的msp430写代码,首先要熟悉这种操作方式,我们不能直接对应一个位去赋值了,而是要使用这种’|=‘,’&=~‘进行赋值操作(对按位与& 和按位或| 不熟悉的朋友需要去了解一下了)。
MSP430 是双向IO口 ,从51转过来的朋友要熟悉去主动设置GPIO口的输入/输出。
另外在使用ccs进行操作的时候,有很多宏定义需要去熟悉, 比如BIT0 =00000001,BIT3=0000010。
如果想要同时拉高/拉低多个io口,可以使用这样的方法: P1OUT |= BIT0+BIT3。P1OUT &=~(BIT0+BIT3);
还有一些特殊的比如CCIE, OUTMOD_x,MC_x等等,需要大家多多熟悉了。
这一部分了解之后, 我们就可以操作很多外设了,跑马灯什么的完全不在话下。
MSP430 这个单片机的中断操作很有趣,每一个IO口都可以是一个中断触发位,只要开启了中断允许位PxIE, 该IO口触发之后就会进入中断,
每一个IO口 P1.0~ P1.7会触发 同一个中断,P1中断:
#pragma vector=PORT1_VECTOR
__interrupt void Port1 (void) //port1 即P1
{
}
同理P2.0~P2.7 会触发P2中断, Px.0-Px.7会触发Px中断。
我们还可以进行判断是哪一位IO口触发的中断, 这时就需要判断中断标志位 ‘IFG’。
在使用中断后,需要清除中断标志位(定时器中断除外),否则中断会持续进行,导致程序卡死。
贴上一段代码,大家感受一下
#include
unsigned int a ;
void init();
void main(void)
{
WDTCTL=WDTPW+WDTHOLD;
init();
while(1)
{
P1OUT = 0; //P1置0
a = P1IN; //读取P1输入
if(a&BIT3)
{
P1OUT = BIT0; //P1.0置1
}
}
}
#pragma vector=PORT1_VECTOR
__interrupt void Port1 (void)
{
if(P1IFG&BIT3)//判断的是P1.3 产生的中断。
{
P1IFG=0x00;//清0 中断标志位
P4OUT^=BIT7; //P4.7置1
}
}
void init()
{
P1IE|=BIT3; //P1^3 中断使能
P1DIR |=(BIT0); // 设置 P1.3为输出
P4DIR |=(BIT7); // 设置 P4.7为输出
__enable_interrupt(); //开启总中断
}
除此之外,还有一些特殊中断位,比如用定时器的捕获比较器输出pwm波时,TACCR0-TACCR4分别对应P1.1-P1.5
使用时需要开启特殊中断位 PxSEL 这个可以等到看完定时器后再进行理解。
关于定时器的操作比较复杂,常用的大概包括:
1.时钟源的选择 TASSELx
2.分频控制 IDx
3.工作模式 MC
4.中断使能 TAIE
5.中断标志 TAIFG
6.捕获/比较器 TACCRx
7.输出模式 OUTMODx
详细的可以翻一翻站内资源,有关于定时器写的非常详细的文章,反复看反复实践,就能快速掌握。
贴上一段代码大家感受一下
//定时器中断LED闪烁
#include
void init()
{
TA0CCTL1=CCIE; //开启捕获比较器1中断
TA0CCR1=50000; //置入要比较的数值
TA0CTL|=TASSEL_1+MC_2+TAIE;//选择SCLK时钟,使用连续模式,开启定时器中断
__enable_interrupt(); //开启总中断
}
void main(void)
{
WDTCTL=WDTPW+WDTHOLD; //关闭看门狗
P4DIR|=BIT7;
P1DIR|=BIT0; //P1.0 为输出方向
P1OUT=0x00; //初始化LED
P1OUT = BIT0;
init();
while(1);
}
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TimerA(void)
{
init();
P1OUT ^= BIT0;
}
下面贴一个定时器产生pwm波的代码,用到了上面说到的特殊中断位
//在P1.3产生pwm波
#include
void main(void)
{
unsigned int PWMPeriod = 21000; //设置PWM周期
WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗
P1DIR |=BIT3; // 设置 P1.3为输出
P1SEL |=BIT3; // 设置 P1.3为TA0.2输出(特殊中断位)
TA0CCR0 = PWMPeriod; // 设置PWM 周期
TA0CCTL2 = OUTMOD_7; // 设置PWM 输出模式7
TA0CTL= TASSEL_2 +MC_1; // 设置定时器A的时钟源为SMCLK, 工作模式为1,从0到CCR0重复计数
TA0CCR2=1000; //设置捕获比较器2, 当计数达到CCR2时触发特殊中断位 P1.3
__enable_interrupt(); //开启总中断
while(1);
}
关于定时器真的有好多需要学习,本人也没有把每一部分完全学明白,等真正用到的时候再回去翻阅。
学一个东西的目标不是把这个东西学通学透,而是用这个东西达到自己的目的,学通学透只是附加品而已。
边学边用,边用边学才能有成效。
下面我将简单举几个例子说一下哪些东西用到了哪部分的知识,哪部分的知识能用来做什么。
简单的方案有很多,我只指出最麻烦的方法方便大家练习/思考
1.流水灯: 基本操作+定时器
这个就很简单了,还可以用delay函数代替定时器,方法有很多,主要可以用来练手。
2.按键调速电机: 基本操作+定时器+中断
定时器产生pwm波,特殊中断io口输出pwm ,通过按键产生中断调整pwm参数实现调速。
3.舵机控制 : 基本操作+定时器
这个和第二个原理相同,可以同时操作
4.LCD1602/12864:基本操作
从头到尾自己手动写一遍的话,会对赋值等有更大的理解,代码敲起来也会更加熟练。
5…
本人的学习过程差不多就是这样,希望文章能给各路新手们起到引导作用。本人也还是新人一枚有很多不懂的地方,知识面也很窄,希望大神们多多批评指正。本人也会不断学习前进,朝着大神的方向前进的。