IO
PxDIR PxOUT PxIN
PxDIR 方向寄存器
作用:配置读/写模式
8位寄存器 初始化00000000 0代表输入 1表示输出
例P1.0输出:00000001
P1DIR=BIT0 //等价于
P1DIR &=~BIT0 //等价于
来自百度文库:正确理解MSP430的PxDIR和PxIN、PxOUT之间的关系
PxOUT输出寄存器
作用:输出
例P1.7->1 P1.0->0 P1OUT,1xxxxxx0
PxIN输入寄存器
作用:读取外部状态
P1.6 若P1IN,x1xxxxxx 则P1.6高电平。x0xxxxxx 低电平。
点亮LED
Light_A_LED
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; //关闭看门狗定时器
P1DIR=BIT0;//将P1.0设为输出 P1DIR=P1DIRBIT0 按位[或]
P1OUT=BIT0;//令P1.0输出高电平
while(1){
}
return 0;
}
LED闪烁
Flash_LED
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW WDTHOLD; // stop watchdog timer
P1DIR=BIT6;//将P1.0设为输出 P1DIR=P1DIRBIT0 按位[或]
P1OUT=BIT6;//令P1.0输出高电平
while(1){
P1OUT^=BIT6;//^异或
__delay_cycles(500000);//500ms延迟(系统时钟约1MHZ)
}
return 0;
}
按键控制LED (PxIN)
检测io电平的方式判断按键
Key_Light_LED
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW WDTHOLD; // stop watchdog timer
P1DIR=BIT6;//将P1.0设为输出 P1DIR=P1DIRBIT0 按位[或]
P1OUT&=~BIT6;//令P1.0输出高电平
P1DIR&=~BIT3;//输入状态
P1REN=BIT3;//使能
P1OUT=BIT3;//上拉电阻
while(1)
{
if(P1IN & BIT3){//未按下
P1OUT&=~BIT6;
}
else{//按下
P1OUT=BIT6;
}
}
return 0;
}
IO中断
P1和P2中断
仅P1、P2有中断
P1-7 共用1个中断服务函数
P2同理 但P2.6-7不可用
中断标志寄存器P1IFG,P2IFG
作用:将中断明确到某一针脚 例
被选择的输入信号:中断边沿选择寄存器设置的上升沿/下降沿
P.S.必须软件复位不然将一直执行中断
中断边沿选择寄存器P1IES,P2IES
设定怎样的电平改变(高 ->低(下降沿) / 低 ->高(上升沿))来判断中断改变PxIFGx
中断使能(开起/关闭 中断)P1IE,P2IE
打开总中断GIE 查看:中断标志寄存器
步骤
打开某端口中断(中断使能)
打开P1.3中断
P1IE=BIT3;
配置触发中断方式(中断边沿选择寄存器)
P1IES=BIT3;//下降沿
清除中断标志位(中断标志寄存器)
P1IFG &= ~BIT3;
打开全局中断GIE
__bis_SR_register(GIE);
配置中断函数(发生中断运行的函数)
pragma vector = 中断向量
中断向量在头文件中查找
msp430g2553
/************************************************************
* Interrupt Vectors (offset from 0xFFE0)
************************************************************/
main.c中断函数模版
执行完后记得清除中断标志位
#pragma vector = PORT1_VECTOR//PORT1_VECTOR中断向量在头文件中查找
__interrupt void Port1_ISR(void)//void Port1_ISR 函数名,随意命名
{
}
按键控制LED (中断)
Key_Light_LED_UsingInterrupt
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW WDTHOLD; // 关闭看门狗定时器
/*初始化LED2所在IO口P1.6为输出*/
P1DIR = BIT6;
/*初始化LED2所在IO口P1.6为低电平,LED2初始状态为灭*/
P1OUT &= ~BIT6;
/*初始化按键所在IO口P1.3为输入*/
P1DIR &= ~BIT3;
/*使能P1.3口的上拉电阻*/
P1REN = BIT3;
P1OUT = BIT3;
/*打开P1.3口中断*/
P1IE = BIT3;
/*设定为下降沿触发*/
P1IES = BIT3;
/*清除中断标志位*/
P1IFG &= ~BIT3;
/*打开全局中断*/
__bis_SR_register(GIE);
while(1)
{
}
return 0;
}
#pragma vector = PORT1_VECTOR
__interrupt void Port1_ISR(void)
{
if(P1IFG & BIT3)//判断是否是P1.3产生中断
{
P1IFG &= ~BIT3;//清除标志位
P1OUT ^= BIT6;
}
}
时钟
MSP430G2553有以下高亮标注的时钟
修改主机时钟MCLK
System_Clock
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW WDTHOLD; // Stop watchdog timer
/*设置MCLK频率*/
DCOCTL = CALDCO_8MHZ;
BCSCTL1 = CALBC1_8MHZ;
//预置有1,2,8,12,17MHZ
/*初始化LED2所在IO口P1.6为输出*/
P1DIR = BIT6;
/*初始化LED2所在IO口P1.6为低电平,LED2初始状态为灭*/
P1OUT &= ~BIT6;
while(1)
{
P1OUT ^= BIT6;
__delay_cycles(500000);
}
return 0;
}
串口配置
MAP430G2553仅有USCI_A0,USCI_B0模块
确认以下参数:
校验位 停止位 数据位 波特率
USCI 初始化和复位
1.UCAxCTL0,USCI_Ax 控制寄存器 0(UCA0CTL0)
UCPEN UCPAR UCMSB UC7BIT UCSPB UCMODEx UCSYNC
//UART模式:异步模式
2.UCAxCTL1,USCI_Ax 控制寄存器 1(UCA0CTL1)
位5~1不需要了解
UCSSELx UCRXEIE UCBRKIE UCDORM UCTXADDR UCTXBRK UCSWRST
3.波特率相关
UCAxMCTL,USCI_Ax 调制控制寄存器
UCAxBR0 USCI_Ax
UCAxMCTL,USCI_Ax 调制控制寄存器
UCBRFx UCBRSx UCOS16
4.状态检测相关
UCAxSTAT,USCI_Ax 状态寄存器
UCLISTEN UCFE UCOE UCPE UCBRK UCRXERR UCADDR UCIDLE UCBUSY
仅需知:位0
5.内容相关
UCAxRXBUF,USCI_Ax 接收缓冲寄存器
UCRXBUFx
UCAxTXBUF,USCI_Ax 发送缓冲寄存器
UCTXBUFx
UCAxIRTCTL,USCI_Ax IrDA 发送缓冲寄存器
UCIRTXPLx UCIRTXCLK
UCIREN
UCAxIRRCTL,USCI_Ax IrDA 接收控制寄存器
**UCIRRXFLx **
UCIRRXPL
UCIRRXFE
6.中断相关
步骤
1.配置系统时钟
串口十分依赖于系统时钟
配置数字控制振荡器为1MHZ
详细参数通过查找msp430g2553.h来查找
msp430g2553.h:
/************************************************************
* Calibration Data in Info Mem
************************************************************/
查找得矫正的数据
msp430g2553.h:
SFR_8BIT(CALDCO_1MHZ); /* DCOCTL Calibration Data for 1MHz */
SFR_8BIT(CALBC1_1MHZ); /* BCSCTL1 Calibration Data for 1MHz *
注意不是:
msp430g2553.h:
#define CAL_DCO_1MHZ (0x0008) /* Index for DCOCTL Calibration Data for 1MHz */
#define CAL_BC1_1MHZ (0x0009) /* Index for BCSCTL1 Calibration Data for 1MHz */
配置DCO(内部振荡器)
main.c
/*配置DCO为1MHz*/
DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;
配置SMCLK(系统子时钟)为DCO
SELMx DIVMx SELS DIVSx DCOR
位三
//默认即为0(DCOCLK),以下代码只是演示用
/*配置SMCLK的时钟源为DCO*/
BCSCTL2 &= ~SELS;
配置SMCLK的分频系数
SELMx DIVMx SELS DIVSx DCOR
位2-1
msp430g2553.h:
#define DIVS0 (0x02) /* SMCLK Divider 0 */
#define DIVS1 (0x04) /* SMCLK Divider 1 */
main.c
/*SMCLK的分频系数置为1*/
BCSCTL2 &= ~(DIVS0 DIVS1);
2.配置串口寄存器
复位
查看:USCI 初始化和复位 \ 2.UCAxCTL1,USCI_Ax 控制寄存器 1(UCA0CTL1) 位 0
UCSSELx UCRXEIE UCBRKIE UCDORM UCTXADDR UCTXBRK UCSWRST
main.c
/*复位USCI_Ax (置1)*/
UCA0CTL1 = UCSWRST;
选择模式
异步模式
查看:USCI 初始化和复位 \ 2.UCAxCTL1,USCI_Ax 控制寄存器 1(UCA0CTL1) 位 0
UCPEN UCPAR UCMSB UC7BIT UCSPB UCMODEx UCSYNC
main.c
/*选择USCI_Ax为UART模式*/
UCA0CTL0 &= ~UCSYNC;
1.奇偶校验
2.MSB
3.字符长度
4.停止位
5.USCI模式
以上五项默认即可
3.配置时钟源
查看:USCI 初始化和复位 \ 2.UCAxCTL1,USCI_Ax 控制寄存器 1(UCA0CTL1) 位 7-6
推荐SMCLK
UCSSELx UCRXEIE UCBRKIE UCDORM UCTXADDR UCTXBRK UCSWRST
/*配置UART时钟源为SMCLK*/
UCA0CTL1 = UCSSEL1;
4.配置波特率
查看:USCI 初始化和复位 \ 波特率相关 15.4.3-4
UCAxBR0,USCI_Ax 波特率控制寄存器 0
UCAxBR1,USCI_Ax 波特率控制寄存器 1
UCBRx
寄存器0低8位
寄存器1高8位
查看:额外 \ 波特率设置 UCOS16=0
将UCBRx 的值(10) - > (16). 例104(10) - > 0x68)(16)。进制转换
UCA0MCTL 根据上图与下图配置UCBRSx
查看:USCI 初始化和复位 \ 波特率相关 \ 15.4.5. UCA0MCTL
UCBRFx UCBRSx UCOS16
main.c
/*配置波特率为9600@1MHz*/
UCA0BR0 = 0x68;
UCA0BR1 = 0x00;//可由低8位表示,无需高8位,故置0
UCA0MCTL = 1 << 1;//“1”左移1位//UCBRSx
5.配置端口
main.c
/*使能端口复用,配置端口*/
P1SEL = BIT1 + BIT2;
P1SEL2 = BIT1 + BIT2;
6.软件清除
查看: 步骤 \ 2.配置串口寄存器 \ 复位 将其置0
/*清除复位位,使能UART*/
UCA0CTL1 &= ~UCSWRST;
7.配置内容
USCI 初始化和复位 \ 5.内容相关 \15.4.8
main.c
UCA0TXBUF = 0xAA;
并设置延时防止发送数据出错
main.c
__delay_cycles(500000);//500ms
Uart_SendChar
#include <msp430.h>
/*
* main.c
*/
int main(void)
{
WDTCTL = WDTPW WDTHOLD; // Stop watchdog timer
/*配置DCO为1MHz*/
DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;
/*配置SMCLK的时钟源为DCO*/
BCSCTL2 &= ~SELS;
/*SMCLK的分频系数置为1*/
BCSCTL2 &= ~(DIVS0 DIVS1);
/*复位USCI_Ax*/
UCA0CTL1 = UCSWRST;
/*选择USCI_Ax为UART模式*/
UCA0CTL0 &= ~UCSYNC;
/*配置UART时钟源为SMCLK*/
UCA0CTL1 = UCSSEL1;
/*配置波特率为9600@1MHz*/
UCA0BR0 = 0x68;
UCA0BR1 = 0x00;
UCA0MCTL = 1 << 1;
/*使能端口复用,配置端口*/
P1SEL = BIT1 + BIT2;
P1SEL2 = BIT1 + BIT2;
/*清除复位位,使能UART*/
UCA0CTL1 &= ~UCSWRST;
while(1)
{
UCA0TXBUF = 0xAA;
__delay_cycles(500000);
}
return 0;
}
PS.
使用虚拟串口需要拔下RXDTXD处左两个跳帽,并横插
串口调试
判断发送状态
查看:串口配置\USCI初始化和复位\4.状态监测相关
UCLISTEN UCFE UCOE UCPE UCBRK UCRXERR UCADDR UCIDLE UCBUSY
位0
UCA0STAT & UCBUSY
Uart_Print
将Uart_SendChar部分代码封装为函数,使代码更为简洁
#include <msp430.h>
#include "stdint.h"
/*
* @fn: void InitSystemClock(void)
* @brief: 初始化系统时钟
* @para: none
* @return: none
* @comment:初始化系统时钟
*/
void InitSystemClock(void)
{
/*配置DCO为1MHz*/
DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;
/*配置SMCLK的时钟源为DCO*/
BCSCTL2 &= ~SELS;
/*SMCLK的分频系数置为1*/
BCSCTL2 &= ~(DIVS0 DIVS1);
}
/*
* @fn: void InitUART(void)
* @brief: 初始化串口,包括设置波特率,数据位,校验位等
* @para: none
* @return: none
* @comment:初始化串口
*/
void InitUART(void)
{
/*复位USCI_Ax*/
UCA0CTL1 = UCSWRST;
/*选择USCI_Ax为UART模式*/
UCA0CTL0 &= ~UCSYNC;
/*配置UART时钟源为SMCLK*/
UCA0CTL1 = UCSSEL1;
/*配置波特率为9600@1MHz*/
UCA0BR0 = 0x68;
UCA0BR1 = 0x00;
UCA0MCTL = 1 << 1;
/*使能端口复用*/
P1SEL = BIT1 + BIT2;
P1SEL2 = BIT1 + BIT2;
/*清除复位位,使能UART*/
UCA0CTL1 &= ~UCSWRST;
}
/*
* @fn: void UARTSendString(uint8_t *pbuff,uint8_t num)
* @brief: 通过串口发送字符串
* @para: pbuff:指向要发送字符串的指针
* num:要发送的字符个数
* @return: none
* @comment:通过串口发送字符串
*/
void UARTSendString(uint8_t *pbuff,uint8_t num)
{
uint8_t cnt = 0;
for(cnt = 0;cnt < num;cnt ++)
{
while(UCA0STAT & UCBUSY);
//__delay_cycles(5000);
UCA0TXBUF = *(pbuff + cnt);
}
}
/*
* @fn: void PrintNumber(uint16_t num)
* @brief: 通过串口发送数字
* @para: num:变量
* @return: none
* @comment:通过串口发送数字
*/
void PrintNumber(uint16_t num)
{
uint8_t buff[6] = {0,0,0,0,0,'\n'};
uint8_t cnt = 0;
for(cnt = 0;cnt < 5;cnt ++)
{
buff[4 - cnt] = (uint8_t)(num % 10 + '0');
num /= 10;
}
UARTSendString(buff,6);
}
/*
* main.c
*/
int main(void)
{
WDTCTL = WDTPW WDTHOLD; // Stop watchdog timer
InitSystemClock();
InitUART();
while(1)
{
PrintNumber(32415);
//UARTSendString(“ASDFGH”,6);
__delay_cycles(500000);
}
return 0;
}
定时器 A
定时器A的四种计数模式
1.停止模式
2.向上模式
其中TACCR0的值由用户自己设定,且与0FFFFh不同
3连续模式
4增加减少模式
TACCR0由用户设置
定时器A的两种工作模式
1.捕捉模式
应用:时间确定
2.比较模式
TAR与TACCRx比较,二者相等时,中断标志置位,若开启了中断.将会执行中断服务函数
用途
借助四种计数模式与两种工作模式可实现以下功能
1.定时
准确的时间间隔
2.产生PWM波
脉冲宽度调制
3.测量频率
测量信号间的时间间隔
定时器A的定时功能
以向上计数模式为例
CCR0->0h时会置位TAIFG标志
CCR0-1->CCR0时会置位CCIFG标志位
步骤
1.配置DCO(内部振荡器)
查看:串口配置\步骤\1.配置系统时钟
/*配置DCO为1MHz*/
DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;
2.设置定时器时钟源
TACTL TASSELx IDx MCx TACLRx TAIE TAIFG
以SMCLK为例
位9-8
/*设置时钟源为SMCLK*/
TA1CTL = TASSEL_2;//TASSEL_2可从msp430g2553.h文件查看
3.设置计数模式
位5-4
/*设置工作模式为Up Mode*/
TA1CTL = MC_1;//同在msp430g2553.h文件
4.设置工作模式
默认比较模式
5.设置定时间隔
设定TA1CCR0的值(上数模式)
/*设置定时间隔*/
TA1CCR0 = 49999;//1MHz 计 50000个数,1/1MHz * 50000 20Hz 0.05s T=TA1CCR0/f
如果使用TAIFG则TA1CCR0 = 49999,如果使用 CCIFG则TA1CCR0 = 50000
6.确定运行1周期
位0
TA1CTL & TAIFG
判断完成后清除标识位
TA1CTL &= ~TAIFG;
P.S.
连续模式默认记65536个数,不可自定义,一般不用
增加减少模式到达TACCR0时产生标识位CCIFG,到达0时产生标识位 TAIFG(计数周期变为两倍向上在向下计数)
Timer_1S
由于始终检测标志位,复杂的程序可能出现计时错误
#include <msp430.h>
#include "stdint.h"
/*
* main.c
*/
int main(void)
{
uint8_t cnt = 0;
WDTCTL = WDTPW WDTHOLD; // Stop watchdog timer
/*配置DCO频率为1MHz*/
DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;
/*设置P1.6为输出*/
P1DIR = BIT6;
/*设置时钟源为SMCLK*/
TA1CTL = TASSEL_2;
/*设置工作模式为Up Mode*/
TA1CTL = MC_1;//Up Mode模式下,16bit Timer计数器 TAR会从0递增到TACCR0,然后回到0,重复这个过程
/*设置定时间隔*/
TA1CCR0 = 49999;//1MHz 计 50000个数,1/1MHz * 50000 20Hz 0.05s
while(1)
{
if(TA1CTL & TAIFG)
{
cnt ++;
TA1CTL &= ~TAIFG;
if(cnt == 20)//0.05s * 20 = 1s
{
P1OUT ^= BIT6;
cnt = 0;
}
}
}
return 0;
}
解决:
使用中断法解决上程序的缺陷
TACTL TASSELx IDx MCx TACLRx TAIE TAIFG
位1
将TAIE位置1
启用TAIFG中断
TA1CTL =TAIE;//可理解为计时器的溢出中断
打开全局中断GIE
__bis_SR_register(GIE);
TAIV
Uart_Clock
#include <msp430.h>
#include "stdint.h"
uint32_t currenttime = 40500;//用来保存时间的变量,初值代表11:15:00
/*
* @fn: void InitSystemClock(void)
* @brief: 初始化系统时钟
* @para: none
* @return: none
* @comment:初始化系统时钟
*/
void InitSystemClock(void)
{
/*配置DCO为1MHz*/
DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;
/*配置SMCLK的时钟源为DCO*/
BCSCTL2 &= ~SELS;
/*SMCLK的分频系数置为1*/
BCSCTL2 &= ~(DIVS0 DIVS1);
}
/*
* @fn: void InitUART(void)
* @brief: 初始化串口,包括设置波特率,数据位,校验位等
* @para: none
* @return: none
* @comment:初始化串口
*/
void InitUART(void)
{
/*复位USCI_Ax*/
UCA0CTL1 = UCSWRST;
/*选择USCI_Ax为UART模式*/
UCA0CTL0 &= ~UCSYNC;
/*配置UART时钟源为SMCLK*/
UCA0CTL1 = UCSSEL1;
/*配置波特率为9600@1MHz*/
UCA0BR0 = 0x68;
UCA0BR1 = 0x00;
UCA0MCTL = 1 << 1;
/*使能端口复用*/
P1SEL = BIT1 + BIT2;
P1SEL2 = BIT1 + BIT2;
/*清除复位位,使能UART*/
UCA0CTL1 &= ~UCSWRST;
}
/*
* @fn: void UARTSendString(uint8_t *pbuff,uint8_t num)
* @brief: 通过串口发送字符串
* @para: pbuff:指向要发送字符串的指针
* num:要发送的字符个数
* @return: none
* @comment:通过串口发送字符串
*/
void UARTSendString(uint8_t *pbuff,uint8_t num)
{
uint8_t cnt = 0;
for(cnt = 0;cnt < num;cnt ++)
{
while(UCA0STAT & UCBUSY);
UCA0TXBUF = *(pbuff + cnt);
}
}
/*
* @fn: void PrintTime(uint32_t time)
* @brief: 通过串口发送当前时间
* @para: time:当前时间
* @return: none
* @comment:通过串口发送当前时间
*/
void PrintTime(uint32_t time)
{
uint8_t charbuff[] = {0,0,':',0,0,':',0,0};
charbuff[7] = (uint8_t)((time % 60) % 10) + '0';//得到当前秒个位
charbuff[6] = (uint8_t)((time % 60) / 10) + '0';//得到当前秒十位
charbuff[4] = (uint8_t)((time % 3600) / 60 % 10) + '0';//得到当前分个位
charbuff[3] = (uint8_t)((time % 3600) / 60 / 10) + '0';//得到当前分十位
charbuff[1] = (uint8_t)((time / 3600) % 10) + '0';//得到当前时个位
charbuff[0] = (uint8_t)(time / 3600 / 10) + '0';//得到当前时十位
UARTSendString("当前时间:",10);
UARTSendString(charbuff,8);
}
/*
* main.c
*/
uint8_t flag = 0;
int main(void)
{
WDTCTL = WDTPW WDTHOLD; // Stop watchdog timer
InitSystemClock();
InitUART();
/*设置P1.6为输出*/
P1DIR = BIT6;
/*设置时钟源为SMCLK*/
TA1CTL = TASSEL_2;
/*设置工作模式为Up Mode*/
TA1CTL = MC_1;
/*设置定时间隔*/
TA1CCR0 = 49999;// 50ms 1MHz 1/1MHz 1ns 50ms / 1ns = 50000 50000 - 1 = 49999
/*开启TAIFG中断*/
TA1CTL = TAIE;
/*打开全局中断*/
__bis_SR_register(GIE);
while(1)
{
if(flag == 1)
{
flag = 0;
P1OUT ^= BIT6;
PrintTime(currenttime);
}
}
return 0;
}
#pragma vector = TIMER1_A1_VECTOR
__interrupt void Time_Tick(void)
{
static uint8_t cnt = 0;
switch(TA1IV)//TAIV自动清除,TAIV只读
{
case 0x02://捕捉/比较寄存器1
break;
case 0x04://捕捉/比较寄存器2
break;
case 0x0A://定时器A溢出
cnt ++;
if(cnt == 20)
{
cnt = 0;//清零计数器
flag = 1;//1s 到了
currenttime ++;//时间加1
currenttime %= 86400;//一天24小时,防止超出
}
break;
default:
break;
}
}
定时器A产生PWM波
PWM波:矩形波 可改变占空比,来实现各种功能例如电机的调速,灯光亮度的控制
使用定时器A的比较工作模式
内部信号通过TA0.0-TA1.2输出
向上模式
Output Mode 1: Set 复位
Output Mode 2
Output Mode 3: Set/Reset 置位/复位
Output Mode 4
Output Mode 5: Reset 复位
Output Mode 6
Output Mode 7: Reset/Set 复位/置位
捕捉/比较寄存器,TACCR1做捕捉/比较寄存器,所以从TA1.1输出,TACCR2则TA1.2输出
TACCR0为最大值无法输出
2、3、6、7产生PWM波形
连续模式
增加减少模式
步骤
1.配置时钟
2.配置工作模式
Breath_LED
使用跳帽连接P1.6,P2.5,并注意在代码中设置P1.6为输入
#include <msp430.h>
/*
* main.c
*/
int main(void)
{
unsigned int cnt = 0;
WDTCTL = WDTPW WDTHOLD; // Stop watchdog timer
/*配置DCO频率为1MHz*/
DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;
/*初始化P1.6为输入*/
P1DIR &= ~BIT6;//否则会可能会有短路
/*设置时钟源为SMCLK*/
TA1CTL = TASSEL1;
/*设置工作模式为Up&Down*/
TA1CTL = MC0MC1;
/*设置TA1CCR0为0x00FF*/
TA1CCR0 = 0x00FF;
/*设置TA1CCR2为0x00FF*/
TA1CCR2 = 0x00FF;//占空比(TACCR0 - TACCR2) / TACCR0,频率=SMCLK/(TACCR0+1)/2
/*设置为比较模式*/
TA1CCTL0 &= ~CAP;
TA1CCTL2 &= ~CAP;
/*设置比较输出模式*/
TA1CCTL2 = OUTMOD_6;//Output Mode 6:Toggle/Set 切换/置位
/*设置IO复用*/
P2SEL = BIT5;
P2DIR = BIT5;
while(1)
{
for(cnt = 0;cnt < 0x00FF;cnt ++)
{
TA1CCR2 = cnt;
__delay_cycles(5000);
}
for(cnt = 0x00FF;cnt > 0;cnt --)
{
TA1CCR2 = cnt;
__delay_cycles(5000);
}
}
return 0;
}
定时器A测定频率(输入捕捉功能)
CMx位15-14
CMx CCISx SCS SCCI CAP OUTMOD CCIE CCI OUT COV CCIFG
从何处输入?
引脚功能表中有CCIxA字样说明可以可作为定时器A输入捕捉比较端口
例:P1.1
P1.1 作为定时器0输入捕捉比较端口
P2.5:
/*P2.5作为捕捉输入(CCI2B)*/
TA1CCTL2 = CCIS0;
P2SEL = BIT5;
CAP 位8
CMx CCISx SCS SCCI CAP OUTMOD CCIE CCI OUT COV CCIF
CMx选择捕捉上升沿/下降沿/两者
CCISx位13-12
CMx CCISx SCS SCCI CAP OUTMOD CCIE CCI OUT COV CCIF
Freq_Meter
#include <msp430.h>
#include "stdint.h"
#include <stdio.h>
uint32_t timestamp = 0;//时间戳
uint16_t capvalue_1 = 0;//第一次捕捉值
uint16_t capvalue_2 = 0;//第二次捕捉值
uint32_t timestamp_1 = 0;//第一次时间戳
uint32_t timestamp_2 = 0;//第二次时间戳
uint32_t totaltime = 0;
float freq = 0;
/*
* @fn: void InitSystemClock(void)
* @brief: 初始化系统时钟
* @para: none
* @return: none
* @comment:初始化系统时钟
*/
void InitSystemClock(void)
{
/*配置DCO为1MHz*/
DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;
/*配置SMCLK的时钟源为DCO*/
BCSCTL2 &= ~SELS;
/*SMCLK的分频系数置为1*/
BCSCTL2 &= ~(DIVS0 DIVS1);
}
/*
* @fn: void InitUART(void)
* @brief: 初始化串口,包括设置波特率,数据位,校验位等
* @para: none
* @return: none
* @comment:初始化串口
*/
void InitUART(void)
{
/*复位USCI_Ax*/
UCA0CTL1 = UCSWRST;
/*选择USCI_Ax为UART模式*/
UCA0CTL0 &= ~UCSYNC;
/*配置UART时钟源为SMCLK*/
UCA0CTL1 = UCSSEL1;
/*配置波特率为9600@1MHz*/
UCA0BR0 = 0x68;
UCA0BR1 = 0x00;
UCA0MCTL = 1 << 1;
/*使能端口复用*/
P1SEL = BIT1 + BIT2;
P1SEL2 = BIT1 + BIT2;
/*清除复位位,使能UART*/
UCA0CTL1 &= ~UCSWRST;
}
/*
* @fn: void UARTSendString(uint8_t *pbuff,uint8_t num)
* @brief: 通过串口发送字符串
* @para: pbuff:指向要发送字符串的指针
* num:要发送的字符个数
* @return: none
* @comment:通过串口发送字符串
*/
void UARTSendString(uint8_t *pbuff,uint8_t num)
{
uint8_t cnt = 0;
for(cnt = 0;cnt < num;cnt ++)
{
while(UCA0STAT & UCBUSY);
UCA0TXBUF = *(pbuff + cnt);
}
}
/*
* @fn: void UARTPrint(uint8_t *pbuff)
* @brief: 通过串口发送字符串
* @para: pbuff:指向要发送字符串的指针
* @return: none
* @comment:通过串口发送字符串,遇到'\0'停止发送
*/
void UARTPrint(uint8_t *pbuff)
{
uint8_t cnt = 0;
while(*(pbuff + cnt) != '\0')
{
while(UCA0STAT & UCBUSY);
UCA0TXBUF = *(pbuff + cnt);
cnt ++;
}
}
/*
* @fn: void PrintFreq(float freq)
* @brief: 通过串口发送频率
* @para: freq:频率
* @return: none
* @comment:通过串口发送频率
*/
void PrintFreq(float freq)
{
uint32_t temp = (uint32_t)(freq * 1000);
uint8_t charbuff[] = {0,0,0,0,0,0,0,0,0};//最大999999.999Hz
int8_t cnt = 0;
for(cnt = 8;cnt >= 0;cnt --)
{
charbuff[cnt] = (uint8_t)(temp % 10) + '0';
temp /= 10;
}
UARTSendString("频率为:",8);
UARTSendString(charbuff,6);
UARTSendString(".",1);
UARTSendString(charbuff + 6,3);
UARTSendString("Hz",2);
}
/*
* main.c
*/
int main(void)
{
WDTCTL = WDTPW WDTHOLD; // Stop watchdog timer
InitSystemClock();
InitUART();
/*设置时钟源为SMCLK*/
TA1CTL = TASSEL_2;
/*设置工作模式为Up Mode*/
TA1CTL = MC_1;
/*设置定时间隔*/
TA1CCR0 = 49999;//50ms
/*开启TAIFG中断*/
TA1CTL = TAIE;
/*TA1,CCR2用于捕捉功能*/
TA1CCTL2 = CAP;
/*上升沿捕捉*/
TA1CCTL2 = CM0;
/*P2.5作为捕捉输入(CCI2B)*/
TA1CCTL2 = CCIS0;
P2SEL = BIT5;
/*允许捕捉比较中断*/
TA1CCTL2 = CCIE;
/*设置时钟源为SMCLK*/
TA0CTL = TASSEL1;
/*设置工作模式为Up&Down*/
TA0CTL = MC0MC1;
/*设置TA0CCR0为0x00FF*/
TA0CCR0 = 0x0AAA;
/*设置TA0CCR1为0x00FF*/
TA0CCR1 = 0x0555;//占空比(TACCR0 - TACCR1) / TACCR0,频率=SMCLK/(TACCR0)/2
/*设置为比较模式*/
TA0CCTL0 &= ~CAP;
TA0CCTL1 &= ~CAP;
/*设置比较输出模式*/
TA0CCTL1 = OUTMOD_6;
/*设置IO复用*/
P1SEL = BIT6;
P1DIR = BIT6;//P1.6生成PWM波
/*打开全局中断*/
__bis_SR_register(GIE);
while(1)
{
__delay_cycles(500000);
freq = (float)(1000000.0) / totaltime;
PrintFreq(freq);
}
return 0;
}
#pragma vector = TIMER1_A1_VECTOR
__interrupt void Time_Tick(void)
{
static uint8_t cnt = 0;
__bis_SR_register(GIE);//允许中断嵌套
switch(TA1IV)
{
case 0x02://捕捉比较中断1
break;
case 0x04://捕捉比较中断2
if(cnt == 0)
{
capvalue_1 = TA1CCR2;//保存第一次捕捉值
timestamp_1 = timestamp;//保存第一次时间戳
cnt ++;
}
else
{
capvalue_2 = TA1CCR2;//保存第二次捕捉值
timestamp_2 = timestamp;//保存第二次时间戳
cnt = 0;
totaltime = (timestamp_2 - timestamp_1) * 50000 + capvalue_2 - capvalue_1;//计算总时间
}
break;
case 0x0A://溢出中断
timestamp ++;
break;
default:
break;
}
}
//定时器1的0通道做溢出中断
//定时器1的2通道做捕捉功能
//定时器0产生PWM波P1.6
//定时器1测频率P2.5
ADC10
A0,A1,A2,A3,A4,A5,A6,A7
分辨率:十位
基准电压:外部
内部
步骤
1.设置时钟源
ADC需要时钟驱动
/*设置ADC时钟MCLK*/
ADC10CTL1 = ADC10SSEL_2;
2.设置分频系数
/*ADC 2分频*/
ADC10CTL1 = ADC10DIV_0;
3.设置基准源
位15-13
SREFx ADC10SHTx ADC10SR REFOUT REFBURST MSC REF2_5V REFON ADC10ON ADC10IE
一般用001
VR+:ADC基准电压的正极
VR-:ADC基准电压的负极
VREF+:内部基准电压
VeREF+:外部基准电压
/*设置ADC基准源*/
ADC10CTL0 = SREF_1;//内部基准源
4.设置采样保持时间(一般无需修改)
/*设置ADC采样保持时间64CLK*/
ADC10CTL0 = ADC10SHT_3;
5.设置采样率(一般无需修改)
/*设置ADC采样率200k*/
ADC10CTL0 &= ~ADC10SR;
6.设置基准电压
/*ADC基准选择2.5V*/
ADC10CTL0 = REF2_5V;
/*ADC基准选择1.5V*/
ADC10CTL0 &= ~REF2_5V;
7.开启基准
位5
SREFx ADC10SHTx ADC10SR REFOUT REFBURST MSC REF2_5V REFON ADC10ON ADC10IE
/*开启基准*/
ADC10CTL0 = REFON;
8.设置ADC输入IO 「一般只改此项」
/*选择ADC输入通道A0*/
ADC10CTL1 = INCH_0;
9.开启通道对应的模拟输入
/*允许A0模拟输入*/
ADC10AE0 = 0x0001;
10.开启ADC总开关
/*开启ADC*/
ADC10CTL0 = ADC10ON;
11.将模拟转化为数字信号
ADC10IFG ENC ADC10SC
位1-0
注意:位0转换完成后会自动清零 即只转换1次
ADC10BUSY
位0
INCHx SHSx ADC10DF ISSH ADC10DIVx ADC10SSELx CONSEQx ADC10BUSY
ADC10MEM
/*
* @fn: uint16_t GetADCValue(void)
* @brief: 进行一次ADC转换并返回ADC转换结果
* @para: none
* @return: ADC转换结果
* @comment:ADC转换结果为10bit,以uint16_t类型返回,低10位为有效数据
*/
uint16_t GetADCValue(void)
{
/*开始转换*/
ADC10CTL0 = ADC10SCENC;
/*等待转换完成*/
while(ADC10CTL1&ADC10BUSY);
/*返回结果*/
return ADC10MEM;
}
函数void InitADC(void) 「1-10」
/*
* @fn: void InitADC(void)
* @brief: 初始化ADC
* @para: none
* @return: none
* @comment:初始化ADC
*/
void InitADC(void)
{
/*设置ADC时钟MCLK*/
ADC10CTL1 = ADC10SSEL_2;
/*ADC 2分频*/
ADC10CTL1 = ADC10DIV_0;
/*设置ADC基准源*/
ADC10CTL0 = SREF_1;
/*设置ADC采样保持时间64CLK*/
ADC10CTL0 = ADC10SHT_3;
/*设置ADC采样率200k*/
ADC10CTL0 &= ~ADC10SR;
/*ADC基准选择2.5V*/
ADC10CTL0 = REF2_5V;
/*开启基准*/
ADC10CTL0 = REFON;
/*选择ADC输入通道A0*/
ADC10CTL1 = INCH_0;//一般仅修改通道相关
/*允许A0模拟输入*/
ADC10AE0 = 0x0001;
/*开启ADC*/
ADC10CTL0 = ADC10ON;
}
Volt_Meter
#include <msp430.h>
#include "stdint.h"
/*
* @fn: void InitSystemClock(void)
* @brief: 初始化系统时钟
* @para: none
* @return: none
* @comment:初始化系统时钟
*/
void InitSystemClock(void)
{
/*配置DCO为1MHz*/
DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;
/*配置SMCLK的时钟源为DCO*/
BCSCTL2 &= ~SELS;
/*SMCLK的分频系数置为1*/
BCSCTL2 &= ~(DIVS0 DIVS1);
}
/*
* @fn: void InitUART(void)
* @brief: 初始化串口,包括设置波特率,数据位,校验位等
* @para: none
* @return: none
* @comment:初始化串口
*/
void InitUART(void)
{
/*复位USCI_Ax*/
UCA0CTL1 = UCSWRST;
/*选择USCI_Ax为UART模式*/
UCA0CTL0 &= ~UCSYNC;
/*配置UART时钟源为SMCLK*/
UCA0CTL1 = UCSSEL1;
/*配置波特率为9600@1MHz*/
UCA0BR0 = 0x68;
UCA0BR1 = 0x00;
UCA0MCTL = 1 << 1;
/*使能端口复用*/
P1SEL = BIT1 + BIT2;
P1SEL2 = BIT1 + BIT2;
/*清除复位位,使能UART*/
UCA0CTL1 &= ~UCSWRST;
}
/*
* @fn: void UARTSendString(uint8_t *pbuff,uint8_t num)
* @brief: 通过串口发送字符串
* @para: pbuff:指向要发送字符串的指针
* num:要发送的字符个数
* @return: none
* @comment:通过串口发送字符串
*/
void UARTSendString(uint8_t *pbuff,uint8_t num)
{
uint8_t cnt = 0;
for(cnt = 0;cnt < num;cnt ++)
{
while(UCA0STAT & UCBUSY);
UCA0TXBUF = *(pbuff + cnt);
}
}
/*
* @fn: void PrintNumber(uint16_t num)
* @brief: 通过串口发送数字
* @para: num:变量
* @return: none
* @comment:通过串口发送数字
*/
void PrintNumber(uint16_t num)
{
uint8_t buff[6] = {0,0,0,0,0,'\n'};
uint8_t cnt = 0;
for(cnt = 0;cnt < 5;cnt ++)
{
buff[4 - cnt] = (uint8_t)(num % 10 + '0');
num /= 10;
}
UARTSendString(buff,6);
}
/*
* @fn: void PrintFloat(float num)
* @brief: 通过串口发送浮点数
* @para: num:变量
* @return: none
* @comment:通过串口发送浮点数,可发送1位整数位+3位小数位
*/
void PrintFloat(float num)
{
uint8_t charbuff[] = {0,'.',0,0,0};
uint16_t temp = (uint16_t)(num * 1000);
charbuff[0] = (uint8_t)(temp / 1000) + '0';
charbuff[2] = (uint8_t)((temp % 1000) / 100) + '0';
charbuff[3] = (uint8_t)((temp % 100) / 10) + '0';
charbuff[4] = (uint8_t)(temp % 10) + '0';
UARTSendString(charbuff,5);
}
/*
* @fn: void InitADC(void)
* @brief: 初始化ADC
* @para: none
* @return: none
* @comment:初始化ADC
*/
void InitADC(void)
{
/*设置ADC时钟MCLK*/
ADC10CTL1 = ADC10SSEL_2;
/*ADC 2分频*/
ADC10CTL1 = ADC10DIV_0;
/*设置ADC基准源*/
ADC10CTL0 = SREF_1;
/*设置ADC采样保持时间64CLK*/
ADC10CTL0 = ADC10SHT_3;
/*设置ADC采样率200k*/
ADC10CTL0 &= ~ADC10SR;
/*ADC基准选择2.5V*/
ADC10CTL0 = REF2_5V;
/*开启基准*/
ADC10CTL0 = REFON;
/*选择ADC输入通道A0*/
ADC10CTL1 = INCH_0;
/*允许A0模拟输入*/
ADC10AE0 = 0x0001;
/*开启ADC*/
ADC10CTL0 = ADC10ON;
}
/*
* @fn: uint16_t GetADCValue(void)
* @brief: 进行一次ADC转换并返回ADC转换结果
* @para: none
* @return: ADC转换结果
* @comment:ADC转换结果为10bit,以uint16_t类型返回,低10位为有效数据
*/
uint16_t GetADCValue(void)
{
/*开始转换*/
ADC10CTL0 = ADC10SCENC;
/*等待转换完成*/
while(ADC10CTL1&ADC10BUSY);
/*返回结果*/
return ADC10MEM;
}
/*
* main.c
*/
int main(void)
{
float voltage = 0;
uint16_t adcvalue = 0;
WDTCTL = WDTPW WDTHOLD; // Stop watchdog timer
InitSystemClock();
InitUART();
InitADC();
while(1)
{
adcvalue = GetADCValue();
voltage = adcvalue * 2.5 / 1023;
UARTSendString("ADC10转换结果为:",17);
PrintNumber(adcvalue);
UARTSendString("相应电压值为:",14);
PrintFloat(voltage);
__delay_cycles(300000);
}
return 0;
}
DTC
ADC_DTC
======额外======
逻辑运算
异或
MSPG2553 引脚配置
波特率设置
======程序======
P2.5产生PWM波,P1.3按钮调整占空比
#include <msp430.h>
long int flag=100;
/*
* main.c
*/
void delay(void)
{
unsigned int tmp;
for(tmp = 120;tmp > 0;tmp--);
}
void PWM_Init()
{
/*配置DCO频率为1MHz*/
DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;
/*初始化P1.6为输入*/
P1DIR &= ~BIT6;
/*设置时钟源为SMCLK*/
TA1CTL = TASSEL1;
/*设置工作模式为Up&Down*/
TA1CTL = MC0MC1;
/*设置TA1CCR0为0x00FF*/
TA1CCR0 = 100;
/*设置TA1CCR2为0x00FF*/
//TA1CCR2 = flag;//占空比(TACCR0 - TACCR2) / TACCR0,频率=SMCLK/(TACCR0+1)/2
/*设置为比较模式*/
TA1CCTL0 &= ~CAP;
TA1CCTL2 &= ~CAP;
/*设置比较输出模式*/
TA1CCTL2 = OUTMOD_6;
/*设置IO复用*/
P2SEL = BIT5;
P2DIR = BIT5;
}
void Key()
{
P1DIR&=~(BIT3+BIT3);//设置IO为输入模式
P1REN=BIT3;//启用上拉/下拉模式
P1OUT=BIT3;//设置为上拉模式
{
if((P1IN&BIT3)==0)//按键按下
{
delay(); //延时用来消除按键的抖动
while(!(P1IN&BIT3)); //等待按键松手
flag-=10; //flag+1 用来改变占空比
if(flag==0) //占空比到100 清零
flag=100;
}
}
}
int main(void)
{
WDTCTL = WDTPW WDTHOLD;
PWM_Init();
// PWM_Init();
for (;;)
{
Key();
TA1CCR2 = flag;
}
}
原文
#include <msp430.h>
long int flag=10;//决定PWM占空比的变量
/****************************************************************************
函数名称 :delay
函数功能:延时 延时的长短由tmp的数值决定
函数参数:无
函数返回值:无
*****************************************************************************/
void delay(void)
{
unsigned int tmp;
for(tmp = 120;tmp > 0;tmp--);
}
/*****************************************************************************
函数名称 :Key
函数功能 :检测按键 用来改变flag的值 进而改变PWM的占空比 目前PWM的精确度为1%
函数参数:无
函数返回值:无
*****************************************************************************/
void Key()
{
P1DIR&=~(BIT3+BIT3);//设置IO为输入模式
P1REN=BIT3+BIT4;//启用上拉/下拉模式
P1OUT=BIT3+BIT4;//设置为上拉模式
{
if((P1IN&BIT3)==0)//按键按下
{
delay(); //延时用来消除按键的抖动
while(!(P1IN&BIT3)); //等待按键松手
flag+=1; //flag+1 用来改变占空比
if(flag>100) //占空比到100 清零
flag=0;
}
if((P1IN&BIT4)==0)//同上注释
{
delay();
while(!(P1IN&BIT4));
flag-=1;
if(flag>100)
flag=0;
}
}
}
/**************************************************************************
函数名称: PWM_Init
函数功能:初始化PWM
函数参数:无
函数返回值:无
***************************************************************************/
void PWM_Init()
{
P1DIR = BIT2; // 设置P1.2为输出
P1SEL = BIT2; // 选择P1.2的PWM功能
P1SEL2 = 0; //选择默认引脚功能
CCR0 = 100; // 设定PWM 周期
CCTL1 = OUTMOD_7;
TACTL = TASSEL_2 + MC_1; // SMCLK时钟 增计数模式
}
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗
PWM_Init();
for (;;)
{
Key();
CCR1 = flag;
}
}
//————————————————
//版权声明:本文为CSDN博主「HopesunIce」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
//原文链接:https://blog.csdn.net/HopesunIce/article/details/78711486
改进,使用中断
#include <msp430.h>
long int flag=100;
/*
* main.c
*/
void delay(void)
{
unsigned int tmp;
for(tmp = 120;tmp > 0;tmp--);
}
void PWM_Init()
{
/*配置DCO频率为1MHz*/
DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;
/*初始化P1.6为输入*/
P1DIR &= ~BIT6;
/*设置时钟源为SMCLK*/
TA1CTL = TASSEL1;
/*设置工作模式为Up&Down*/
TA1CTL = MC0MC1;
/*设置TA1CCR0为0x00FF*/
TA1CCR0 = 100;
/*设置TA1CCR2为0x00FF*/
//TA1CCR2 = flag;//占空比(TACCR0 - TACCR2) / TACCR0,频率=SMCLK/(TACCR0+1)/2
/*设置为比较模式*/
TA1CCTL0 &= ~CAP;
TA1CCTL2 &= ~CAP;
/*设置比较输出模式*/
TA1CCTL2 = OUTMOD_6;
/*设置IO复用*/
P2SEL = BIT5;
P2DIR = BIT5;
}
void Key()
{
/*初始化按键所在IO口P1.3为输入*/
P1DIR &= ~BIT3;
/*使能P1.3口的上拉电阻*/
P1REN = BIT3;
P1OUT = BIT3;
/*打开P1.3口中断*/
P1IE = BIT3;
/*设定为下降沿触发*/
P1IES = BIT3;
/*清除中断标志位*/
P1IFG &= ~BIT3;
/*打开全局中断*/
__bis_SR_register(GIE);
}
int main(void)
{
WDTCTL = WDTPW WDTHOLD;
PWM_Init();
// PWM_Init();
for (;;)
{
Key();
TA1CCR2 = flag;
}
}
#pragma vector = PORT1_VECTOR
__interrupt void Port1_ISR(void)
{if(P1IFG & BIT3)//判断是否是P1.3产生中断
{
P1IFG &= ~BIT3;//清除标志位
flag-=10; //flag+1 用来改变占空比
if(flag==0) //占空比到100 清零
flag=100;
}
}
#include "msp430g2553.h"
int flag=500;
int main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
DCOCTL = CALDCO_16MHZ;
BCSCTL1 = CALBC1_16MHZ;
P1DIR&=~BIT6;//配置LEDP1.6为输入
P1DIR&=~BIT0;//配置LEDP1.0为输入
TA0CTL=BIT9;//配置为SMCLK
TA0CTL&=~BIT8;
TA0CTL&=~TACLR;
TA0CTL=MC_3;//UP/DOWN 模式
TA0CCR0=500;
TA0CCR1=0;
TA0CCTL1=OUTMOD_6;
P1DIR=BIT2;
P1SEL=BIT2;
TA1CTL=BIT9;//配置为SMCLK
TA1CTL&=~BIT8;
TA1CTL&=~TACLR;
TA1CTL=MC_3;
TA1CCR0 = 500;
TA1CCR2 = 300;//占空比(TACCR0 - TACCR2) / TACCR0,频率=SMCLK/(TACCR0+1)/2
TA1CCTL2 = OUTMOD_6;//Output Mode 6:Toggle/Set 切换/置位
P2SEL = BIT5;
P2DIR = BIT5;
while(1)
{
//LPM3;
/*初始化按键所在IO口P1.3为输入*/
P1DIR &= ~BIT3;
/*使能P1.3口的上拉电阻*/
P1REN = BIT3;
P1OUT = BIT3;
/*打开P1.3口中断*/
P1IE = BIT3;
/*设定为下降沿触发*/
P1IES = BIT3;
/*清除中断标志位*/
P1IFG &= ~BIT3;
/*打开全局中断*/
__bis_SR_register(GIE);
TA0CCR1=flag;
}
return 0;
}
//————————————————
//版权声明:本文为CSDN博主「角落de男孩」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
//原文链接:https://blog.csdn.net/qq_35813104/article/details/72823234
#pragma vector = PORT1_VECTOR
__interrupt void Port1_ISR(void)
{
if(P1IFG & BIT3)//判断是否是P1.3产生中断
{
P1IFG &= ~BIT3;//清除标志位
//P1OUT ^= BIT6;
if (flag<=500) {
flag+=100;
}else{
flag=0;
}
}
}
Kuruma
#include <msp430g2553.h>
char i=0;
char leftspeed=10;
char rightspeed=10;
void init()
{
P1DIR &= ~(BIT3+BIT4+BIT1+BIT2);
P2DIR=BIT3;
P2DIR=BIT2;
TA0CTL=MC_1+TASSEL_2+TACLR;
TA0CCTL0=CCIE;
TA0CCR0=50;
}
void main(void)
{
WDTCTL = WDTPW WDTHOLD;
P1DIR = BIT6;
P1OUT &= ~BIT6;
init();
__bis_SR_register(GIE);
while(1)
{
if(!(P1IN & BIT3)) //判断是否P1.3产生中断
{
P1OUT ^= BIT6;
leftspeed=10;
rightspeed=20;
}
else if(!(P1IN & BIT4)) //判断是否P1.3产生中断
{
P1OUT ^= BIT6;
leftspeed=20;
rightspeed=10;
}
if(!(P1IN & BIT1))
{
leftspeed=40;
rightspeed=5;
}
if(!(P1IN & BIT2))
{
leftspeed=40;
rightspeed=5;
}
}
}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A(void)
{
__disable_interrupt();
i++;
if(i<leftspeed)
{
P2OUT=BIT3;
}
else if(leftspeed<=i<=100)
{
P2OUT&=~BIT3;
}
if(i<rightspeed)
{
P2OUT=BIT2;
}
else if(rightspeed<=i<=100)
{
P2OUT&=~BIT2;
}
if(i==100)
{i=0;}
__enable_interrupt();
}