文章目录
- 开发环境
- 板子介绍
- 官网示例代码下载
- MSP430普通IO口控制
- IO口外部中断
- MSP430时钟系统
- MSP430不精确延时之delay_ms
- MSP430定时器_CCR0溢出中断
- MSP430定时器_定时器计数溢出中断
- MSP430定时器_PWM波形产生
- MSP430串口_收发
- 9600波特率
- 115200 波特率
- MSP430ADC
- MSP430 Flash读写
开发环境
CCS软件下载:https://www.ti.com/tool/download/CCSTUDIO
建议别搞太高版本。
板子介绍
P1.0 接了LED 输出低电平点亮小灯
P1.6 接了LED
P1.3 接了KEY 按键按下是低电平
官网示例代码下载
https://www.ti.com.cn/product/cn/MSP430G2553#software-development
MSP430普通IO口控制
使用按键控制灯。学习常用的IO口寄存器。
//******************************************************************************
// MSP430G2xx3 Demo - Software Poll P1.4, Set P1.0 if P1.4 = 1
//
// Description: Poll P1.4 in a loop, if hi P1.0 is set, if low, P1.0 reset.
// ACLK = n/a, MCLK = SMCLK = default DCO
//
// MSP430G2xx3
// -----------------
// /|\| XIN|-
// | | |
// --|RST XOUT|-
// /|\ | |
// --o--|P1.3 P1.0|-->LED
// \|/
//
// D. Dang
// Texas Instruments, Inc
// December 2010
// Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10
//******************************************************************************
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
P1DIR |= BIT0; // Set P1.0 to output direction
P1DIR &= ~BIT3; //输入
P1REN |= BIT3; //上拉下拉使能
P1OUT |= BIT3; //上拉
while (1) // Test P1.4
{
if ((BIT3 & P1IN) == 0) // 按键按下
P1OUT |= BIT0;
else
P1OUT &= ~BIT0;
}
}
WDTCTL = WDTPW + WDTHOLD;
这一行代码停止了看门狗定时器(Watchdog Timer),以防止系统复位。WDTCTL是一个特殊寄存器,用于配置和控制看门狗定时器。通过将WDTPW和WDTHOLD的值相加,可以将看门狗定时器设置为停止状态。
P1DIR |= BIT0;
这一行代码将P1.0引脚的方向设置为输出。P1DIR是P1端口的方向寄存器,BIT0是一个宏定义,表示二进制数1。使用按位或操作符(|=)可以将P1DIR寄存器的BIT0位置1,将P1.0设置为输出方向。
在循环中,程序通过检查P1.3引脚的输入状态来控制P1.0引脚的输出状态。如果P1.3引脚的输入为低电平(按键按下),则将P1.0引脚设置为高电平。如果P1.3引脚的输入为高电平(按键未按下),则将P1.0引脚设置为低电平。
IO口外部中断
IO口外部中断是一种特殊的中断,它允许外部事件触发微控制器的中断服务程序。它的存在有以下几个意义和用途:
事件检测和响应:外部中断可以用于检测和响应外部事件,例如按键按下、传感器状态变化、信号边沿等。当外部事件发生时,触发外部中断,微控制器可以立即中断当前任务,执行与事件相关的中断服务程序,从而及时响应外部事件。
节省处理器资源:通过使用外部中断,可以节省处理器资源。相比于不断地轮询输入状态,使用外部中断可以在外部事件发生时立即中断处理,避免了处理器不断轮询的浪费。这样,处理器可以继续执行其他任务,而无需关注外部事件,只有在事件发生时才会中断处理。
实时性和精确性:外部中断的响应速度很快,可以实现实时性要求高的应用。它可以在微秒级别的时间内检测到外部事件,并立即中断处理。这对于需要高精度和及时响应的应用非常重要,如控制系统、测量和采样系统等。
多任务处理:外部中断允许多任务处理。通过将不同的外部事件分配给不同的中断服务程序,可以同时处理多个任务。这样,可以在同一个微控制器上实现多个功能模块的并行处理,提高系统的效率和灵活性。
WDTCTL = WDTPW + WDTHOLD;:停止看门狗定时器。MSP430微控制器通常配备了一个看门狗定时器,用于在程序执行期间检测和防止系统锁死。
P1DIR |= BIT0;:将P1.0引脚设置为输出方向。这意味着P1.0被配置为输出引脚,可以控制外部设备。
P1IE |= BIT3;:启用P1.3引脚的中断功能。当发生与P1.3引脚相关的中断时,将触发相应的中断服务程序。
P1IES |= BIT3;:配置P1.3引脚的中断触发边沿。在本例中,配置为高电平到低电平的触发边沿。
P1REN |= BIT3;:启用P1.3引脚的上拉电阻。这意味着P1.3引脚与上拉电阻连接,可以检测外部连接的开关状态。
P1IFG &= ~BIT3;:清除P1.3引脚的中断标志位。确保在进入中断服务程序之前,将中断标志位重置为未触发状态。
__bis_SR_register(LPM4_bits + GIE);:将微控制器设置为低功耗模式4(LPM4),并启用全局中断(GIE)。进入低功耗模式后,微控制器将等待中断事件的发生。
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
P1OUT ^= BIT0; // P1.0 = toggle
P1IFG &= ~BIT3; // P1.3 IFG cleared
}
这是一个中断服务程序,是固有写法,其中PORT1_VECTOR是中断向量入口,Port_1是中断函数名称。
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
P1DIR |= BIT0; // Set P1.0 to output direction
P1IE |= BIT3; // P1.3 interrupt enabled
P1IES |= BIT3; // P1.3 Hi/lo edge
P1REN |= BIT3; // Enable Pull Up on SW2 (P1.3)
P1IFG &= ~BIT3; // P1.3 IFG cleared
//BIT3 on Port 1 can be used as Switch2
__bis_SR_register(LPM4_bits + GIE); // Enter LPM4 w/interrupt
}
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
P1OUT ^= BIT0; // P1.0 = toggle
P1IFG &= ~BIT3; // P1.3 IFG cleared
}
MSP430时钟系统
基本时钟模块+支持低系统成本和超低功耗。使用三个内部时钟信号,用户可以选择性能和低功耗之间的最佳平衡。基本时钟模块+可以在完全软件控制下配置为不需要任何外部元件、一个外部电阻、一个或两个外部晶体,或者谐振器进行操作。
基本时钟模块+包括两个、三个或四个时钟源:
• LFXT1CLK:低频/高频振荡器,可与低频手表晶体或外部时钟源(32768 Hz)或标准晶体、谐振器或外部时钟源(400 kHz至16 MHz范围内)一起使用。
• XT2CLK:可选的高频振荡器,可与标准晶体、谐振器或外部时钟源(400 kHz至16 MHz范围内)一起使用。
• DCOCLK:内部数字控制振荡器(DCO)。
• VLOCLK:内部超低功耗低频振荡器,典型频率为12 kHz。
基本时钟模块+提供三个时钟信号:
• ACLK:辅助时钟。ACLK可在软件中选择LFXT1CLK或VLOCLK。ACLK可被1、2、4或8分频。ACLK可针对各个外设模块进行软件选择。
• MCLK:主时钟。MCLK可在软件中选择LFXT1CLK、VLOCLK、XT2CLK(如果芯片上可用)或DCOCLK。MCLK可被1、2、4或8分频。MCLK由CPU和系统使用。
• SMCLK:子主时钟。SMCLK可在软件中选择LFXT1CLK、VLOCLK、XT2CLK(如果芯片上可用)或DCOCLK。SMCLK可被1、2、4或8分频。SMCLK可针对各个外设模块进行软件选择。
该代码的作用是配置 MSP430G2xx3 微控制器的时钟信号输出,其中 P1.0 引脚输出 ACLK 时钟信号,P1.4 引脚输出 SMCLK 时钟信号,P1.1 引脚输出 MCLK/10 时钟信号。在无限循环中,不断地在 P1.1 引脚上输出高电平和低电平信号,形成一个方波输出,模拟了MCLK时钟快慢。
//******************************************************************************
// MSP430G2xx3 Demo - Basic Clock, Output Buffered SMCLK, ACLK and MCLK/10
//
// Description: Buffer ACLK on P1.0, default SMCLK(DCO) on P1.4 and MCLK/10 on
// P1.1.
// ACLK = LFXT1 = 32768, MCLK = SMCLK = default DCO
// //* External watch crystal installed on XIN XOUT is required for ACLK *//
//
// MSP430G2xx3
// -----------------
// /|\| XIN|-
// | | | 32kHz
// --|RST XOUT|-
// | |
// | P1.4/SMCLK|-->SMCLK = Default DCO
// | P1.1|-->MCLK/10 = DCO/10
// | P1.0/ACLK|-->ACLK = 32kHz
//
// D. Dang
// Texas Instruments Inc.
// December 2010
// Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10
//******************************************************************************
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW +WDTHOLD; // Stop Watchdog Timer
//1Mhz
if (CALBC1_1MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set range
DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation */
/* //8Mhz
if (CALBC1_8MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_8MHZ; // Set range
DCOCTL = CALDCO_8MHZ; // Set DCO step + modulation */
/* //12Mhz
if (CALBC1_12MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_12MHZ; // Set range
DCOCTL = CALDCO_12MHZ; // Set DCO step + modulation*/
/* //16Mhz
if (CALBC1_16MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_16MHZ; // Set range
DCOCTL = CALDCO_16MHZ; // Set DCO step + modulation*/
P1DIR |= 0x13; // P1.0,1 and P1.4 outputs
P1SEL |= 0x11; // P1.0,4 ACLK, SMCLK output
while(1)
{
P1OUT |= 0x02; // P1.1 = 1
P1OUT &= ~0x02; // P1.1 = 0
}
}
MSP430不精确延时之delay_ms
__delay_cycles是编译器内置的空指令运算,通过宏定义包装,成为不精确延时之delay_ms。
#include <msp430.h>
#define CPU_F ( (double) 16000000)
#define delay_us( x ) __delay_cycles( (long) (CPU_F * (double) x / 1000000.0) )
#define delay_ms( x ) __delay_cycles( (long) (CPU_F * (double) x / 1000.0) )
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop Watchdog Timer
//16Mhz
if (CALBC1_16MHZ == 0xFF) // If calibration constant erased
{
while (1)
; // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_16MHZ; // Set range
DCOCTL = CALDCO_16MHZ; // Set DCO step + modulation
P1DIR |= BIT0;
while (1)
{
P1OUT ^= BIT0; //亦或计算
delay_ms(100);
}
}
MSP430定时器_CCR0溢出中断
下面的设置是50ms的中断。
SMCLK是1MHZ,此时CCR0 = 50000,定时器计数到CCR0 即是等于50ms。
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
//1Mhz
if (CALBC1_1MHZ == 0xFF) // If calibration constant erased
{
while (1)
; // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set range
DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation */
P1DIR |= 0x01; // P1.0 output
CCTL0 = CCIE; // CCR0 interrupt enabled
CCR0 = 50000;
TACTL = TASSEL_2 + MC_1; // SMCLK, Up to CCR0
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
}
// Timer A0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A(void)
{
P1OUT ^= BIT0; // Toggle P1.0
}
下面是四种计数模式,我们刚才的选择是让其计数到CCR0就 产生溢出中断。
MSP430定时器_定时器计数溢出中断
定时器计数溢出中断的中断向量是TIMER0_A1_VECTOR,这个中断向量入口也是CCR1 、CCR2 溢出的入口,在内部依靠TA0IV 寄存器判断具体的中断来源。
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1DIR |= 0x01; // P1.0 output
TACTL = TASSEL_2 + MC_2 + TAIE; // SMCLK, contmode, interrupt
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
}
// Timer_A3 Interrupt Vector (TA0IV) handler
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A(void)
{
switch( TA0IV )
{
case 2: break; // CCR1 not used
case 4: break; // CCR2 not used
case 10: P1OUT ^= 0x01; // overflow
break;
}
}
针对于CCR1之类的溢出也是不常用的,下面的代码看看就好。
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1SEL |= 0x06; // P1.1 - P1.2 option select
P1DIR |= 0x07; // P1.0 - P1.2 outputs
CCTL0 = OUTMOD_4 + CCIE; // CCR0 toggle, interrupt enabled
CCTL1 = OUTMOD_4 + CCIE; // CCR1 toggle, interrupt enabled
TACTL = TASSEL_2 + MC_2 + TAIE; // SMCLK, Contmode, int enabled
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
}
// Timer A0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0 (void)
{
CCR0 += 200; // Add Offset to CCR0
}
// Timer_A2 Interrupt Vector (TA0IV) handler
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A1(void)
{
switch( TA0IV )
{
case 2: CCR1 += 1000; // Add Offset to CCR1
break;
case 10: P1OUT ^= 0x01; // Timer_A3 overflow
break;
}
}
MSP430定时器_PWM波形产生
PWM(Pulse Width Modulation,脉宽调制)波形在电子和控制系统中有着广泛的应用,它具有以下几个重要的作用:
模拟信号生成:PWM波形可以通过调整脉冲的占空比来模拟产生连续的模拟信号。通过改变脉冲的宽度(占空比),可以实现不同的平均电平值,从而生成与输入信号强度或控制信号相关的模拟输出。这使得PWM成为模拟电压和模拟电流控制的一种常见技术。
电机控制:PWM广泛应用于电机驱动和速度控制中。通过在电机绕组上施加PWM波形,可以控制电机的转速和扭矩。通过调整脉冲的占空比,可以改变电机驱动电压的平均值,从而控制电机的转速。
LED亮度控制:PWM被广泛用于LED亮度调节。通过改变PWM波形的占空比,可以控制LED的亮度。当PWM波形的占空比较大时,LED处于高亮度状态;当占空比较小时,LED处于低亮度状态。通过快速调整PWM波形的占空比,可以实现灯光的平滑过渡和精确亮度控制。
电源管理:PWM被用于电源管理和节能控制中。通过在开关电源中采用PWM控制,可以调整开关管的通断时间,从而调节输出电压或电流。这种方式可以提高电源的效率和稳定性,并减少功耗。
数字信号传输:PWM波形还可以用作数字信号传输的一种方式。在某些应用中,可以使用PWM波形来编码和传输数字信息。通过改变脉冲的频率或占空比,可以表示不同的数字值,从而实现简单的数字通信。
下面是MSP430的PMW输出模式:
下面的代码是让P1.2输出50%占空比的1kHZ波形。
// | P1.2/TA1|--> CCR1 - 50% PWM
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
//1Mhz
if (CALBC1_1MHZ == 0xFF) // If calibration constant erased
{
while (1)
; // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set range
DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation */
P1DIR |= BIT2;
P1SEL |= BIT2;
CCR0 = 1000; // PWM Period/2
CCTL1 = OUTMOD_7; // CCR1 toggle/set
CCR1 = 500; // CCR1 PWM duty cycle
TACTL = TASSEL_2 + MC_3; // SMCLK, up-down mode
__bis_SR_register(LPM0_bits); // Enter LPM0
}
MSP430串口_收发
9600波特率
// MSP430G2xx3 Demo - USCI_A0, 9600 UART Echo ISR, DCO SMCLK
//
// Description: Echo a received character, RX ISR used. Normal mode is LPM0.
// USCI_A0 RX interrupt triggers TX Echo.
// Baud rate divider with 1MHz = 1MHz/9600 = ~104.2
// ACLK = n/a, MCLK = SMCLK = CALxxx_1MHZ = 1MHz
//
// MSP430G2xx3
// -----------------
// /|\| XIN|-
// | | |
// --|RST XOUT|-
// | |
// | P1.2/UCA0TXD|------------>
// | | 9600 - 8N1
// | P1.1/UCA0RXD|<------------
//
// D. Dang
// Texas Instruments Inc.
// February 2011
// Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10
//******************************************************************************
#include <msp430.h>
void Send_Byte(char data)
{
while (!(IFG2 & UCA0TXIFG))
; // USCI_A0 TX buffer ready?
UCA0TXBUF = data; // TX -> RXed character
}
void Print_Str(char *s)
{
while (*s != '\0')
{
Send_Byte(*s++);
}
}
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
if (CALBC1_1MHZ == 0xFF) // If calibration constant erased
{
while (1)
; // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;
P1SEL = BIT1 + BIT2; // P1.1 = RXD, P1.2=TXD
P1SEL2 = BIT1 + BIT2; // P1.1 = RXD, P1.2=TXD
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 104; // 1MHz 9600
UCA0BR1 = 0; // 1MHz 9600
UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, interrupts enabled
}
// Echo back RXed character, confirm TX buffer is ready first
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
while (!(IFG2 & UCA0TXIFG))
; // USCI_A0 TX buffer ready?
UCA0TXBUF = UCA0RXBUF; // TX -> RXed character
}
115200 波特率
// MSP430G2xx3 Demo - USCI_A0, 115200 UART Echo ISR, DCO SMCLK
//
// Description: Echo a received character, RX ISR used. Normal mode is LPM0.
// USCI_A0 RX interrupt triggers TX Echo.
// Baud rate divider with 1MHz = 1MHz/115200 = ~8.7
// ACLK = n/a, MCLK = SMCLK = CALxxx_1MHZ = 1MHz
//
// MSP430G2xx3
// -----------------
// /|\| XIN|-
// | | |
// --|RST XOUT|-
// | |
// | P1.2/UCA0TXD|------------>
// | | 115200 - 8N1
// | P1.1/UCA0RXD|<------------
//
// D. Dang
// Texas Instruments Inc.
// February 2011
// Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10
//******************************************************************************
#include <msp430.h>
void Send_Byte(char data)
{
while (!(IFG2 & UCA0TXIFG))
; // USCI_A0 TX buffer ready?
UCA0TXBUF = data; // TX -> RXed character
}
void Print_Str(char *s)
{
while (*s != '\0')
{
Send_Byte(*s++);
}
}
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
if (CALBC1_1MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;
P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
P1SEL2 = BIT1 + BIT2;
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 8; // 1MHz 115200
UCA0BR1 = 0; // 1MHz 115200
UCA0MCTL = UCBRS2 + UCBRS0; // Modulation UCBRSx = 5
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, interrupts enabled
}
// Echo back RXed character, confirm TX buffer is ready first
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = UCA0RXBUF; // TX -> RXed character
}
MSP430ADC
下面是ADC单通道转换代码。多通道较为复杂,这里不叙述。
#include <msp430.h>
#define CPU_F ( (double) 1000000)
#define delay_us( x ) __delay_cycles( (long) (CPU_F * (double) x / 1000000.0) )
#define delay_ms( x ) __delay_cycles( (long) (CPU_F * (double) x / 1000.0) )
unsigned int volt;
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; /* Stop WDT */
ADC10CTL0 = ADC10SHT_2 + ADC10ON ; // ADC10ON, interrupt enabled
ADC10CTL1 = INCH_4; // input A4
ADC10AE0 |= BIT4; // PA.4 ADC option select
while (1)
{
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
while ((ADC10IFG & ADC10CTL0)==0)
; //MEM5触发IFG5 意味着有了新的转换结果
volt = ADC10MEM;
volt=volt*3.3*100/1024;
delay_ms(100);
}
}
MSP430 Flash读写
#include <msp430.h>
char value; // 8-bit value to write to segment A
// Function prototypes
void write_SegC (char value);
void copy_C2D (void);
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
if (CALBC1_1MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1MHz
DCOCTL = CALDCO_1MHZ;
FCTL2 = FWKEY + FSSEL0 + FN1; // MCLK/3 for Flash Timing Generator
value = 0; // initialize value
while(1) // Repeat forever
{
write_SegC(value++); // Write segment C, increment value
copy_C2D(); // Copy segment C to D
__no_operation(); // SET BREAKPOINT HERE
}
}
void write_SegC (char value)
{
char *Flash_ptr; // Flash pointer
unsigned int i;
Flash_ptr = (char *) 0x1040; // Initialize Flash pointer
FCTL1 = FWKEY + ERASE; // Set Erase bit
FCTL3 = FWKEY; // Clear Lock bit
*Flash_ptr = 0; // Dummy write to erase Flash segment
FCTL1 = FWKEY + WRT; // Set WRT bit for write operation
for (i=0; i<64; i++)
{
*Flash_ptr++ = value; // Write value to flash
}
FCTL1 = FWKEY; // Clear WRT bit
FCTL3 = FWKEY + LOCK; // Set LOCK bit
}
void copy_C2D (void)
{
char *Flash_ptrC; // Segment C pointer
char *Flash_ptrD; // Segment D pointer
unsigned int i;
Flash_ptrC = (char *) 0x1040; // Initialize Flash segment C pointer
Flash_ptrD = (char *) 0x1000; // Initialize Flash segment D pointer
FCTL1 = FWKEY + ERASE; // Set Erase bit
FCTL3 = FWKEY; // Clear Lock bit
*Flash_ptrD = 0; // Dummy write to erase Flash segment D
FCTL1 = FWKEY + WRT; // Set WRT bit for write operation
for (i=0; i<64; i++)
{
*Flash_ptrD++ = *Flash_ptrC++; // copy value segment C to segment D
}
FCTL1 = FWKEY; // Clear WRT bit
FCTL3 = FWKEY + LOCK; // Set LOCK bit
}
PS: 有代码需要做可以私信。