基于CCS工程MSP430串口升级(一)

2020-03-25来源: eefocus关键字:CCS工程  MSP430  串口升级

第一次接触MSP430的芯片,第一次使用CCS开发环境,花了将近一个星期的时间,才把MSP430串口升级做出来。


同样分成BOOT,APP,上位机,三个部分来讲解。


BOOT

在lnk_msp430fg479.cmd中修改BOOT Flash的起始地址(0xF000~0xFFE0),将近4K的Flash

MEMORY

{

    SFR                     : origin = 0x0000, length = 0x0010

    PERIPHERALS_8BIT        : origin = 0x0010, length = 0x00F0

    PERIPHERALS_16BIT       : origin = 0x0100, length = 0x0100

    RAM                     : origin = 0x0200, length = 0x0800

    INFOA                   : origin = 0x10C0, length = 0x0040

    INFOB                   : origin = 0x1080, length = 0x0040

    INFOC                   : origin = 0x1040, length = 0x0040

    INFOD                   : origin = 0x1000, length = 0x0040

//    FLASH                   : origin = 0x1100, length = 0xEEE0 

    FLASH                   : origin = 0xF000, length = 0x0FE0

    INT00                   : origin = 0xFFE0, length = 0x0002

    INT01                   : origin = 0xFFE2, length = 0x0002

    INT02                   : origin = 0xFFE4, length = 0x0002

    INT03                   : origin = 0xFFE6, length = 0x0002

    INT04                   : origin = 0xFFE8, length = 0x0002

    INT05                   : origin = 0xFFEA, length = 0x0002

    INT06                   : origin = 0xFFEC, length = 0x0002

    INT07                   : origin = 0xFFEE, length = 0x0002

    INT08                   : origin = 0xFFF0, length = 0x0002

    INT09                   : origin = 0xFFF2, length = 0x0002

    INT10                   : origin = 0xFFF4, length = 0x0002

    INT11                   : origin = 0xFFF6, length = 0x0002

    INT12                   : origin = 0xFFF8, length = 0x0002

    INT13                   : origin = 0xFFFA, length = 0x0002

    INT14                   : origin = 0xFFFC, length = 0x0002

    RESET                   : origin = 0xFFFE, length = 0x0002

}


中断向量重映射,BOOT中断函数跳转到APP中断函数

// Timer A0 interrupt service routine

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)

#pragma vector=TIMERA0_VECTOR

__interrupt void Timer_A (void)

#elif defined(__GNUC__)

void __attribute__ ((interrupt(TIMERA0_VECTOR))) Timer_A (void)

#else

#error Compiler not supported!

#endif

{

asm(" br &0xEFEC;");

}


#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)

#pragma vector=SD16A_VECTOR

__interrupt void SD16ISR(void)

#elif defined(__GNUC__)

void __attribute__ ((interrupt(SD16A_VECTOR))) SD16ISR (void)

#else

#error Compiler not supported!

#endif

{

asm(" br &0xEFEE;");

}


// Watchdog Timer interrupt service routine

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)

#pragma vector=WDT_VECTOR

__interrupt void watchdog_timer(void)

#elif defined(__GNUC__)

void __attribute__ ((interrupt(WDT_VECTOR))) watchdog_timer (void)

#else

#error Compiler not supported!

#endif

{

asm(" br &0xEFF4;");

}


#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)

#pragma vector=USCIAB0RX_VECTOR

__interrupt void USCI_A0_rx (void)

#elif defined(__GNUC__)

void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCI_A0_rx (void)

#else

#error Compiler not supported!

#endif

{

// printf("%c",UCA0RXBUF);

// if(isBoot==2)

// {

// u16 rxAddr = 0xBFF2  ;

// ((void (*)(void))appAddr)();

asm(" br &0xEFF2;");

// }

// else

// {

// rx_buf[rx_buf_index++] = UCA0RXBUF;

// if(rx_buf_index>=RX_SIZE)

// rx_buf_index = 0;

// }

}


这边需要注意的一点是,APP和BOOT的中断函数不要有冲突,有重复。比如APP有串口接收中断,BOOT就不能有串口接收中断。至于为什么,后面再解释。在这里,APP的内容比较多,必须要有串口接收中断提高实时性,那就只能委屈BOOT轮询串口缓冲。


while(1)

{

// delay_ms(1000);

for(i=0;i<0x7fff;i++)

{

if(IFG2&UCA0RXIFG)

{

i=0;

rx_buf[rx_buf_index++] = UCA0RXBUF;

if(rx_buf_index>=RX_SIZE)

rx_buf_index = 0;

}

}


if(rx_buf_index > 5)

{

if(rx_buf[0]==MODBUS_DO)

{

crc = CRC16(rx_buf, rx_buf_index-2);

if(crc == ((rx_buf[rx_buf_index-1]<<8)|rx_buf[rx_buf_index-2]))

{

switch(rx_buf[1])

{

case 0x03:

Modbus_Function_3();

break;

case 0x10:

Modbus_Function_10();

break;

case 0x45:

Modbus_Function_45();

break;

}

}

}

rx_buf_index = 0;

}

}


Flash读写,MSP430FG479这款MCU,一个片区512字节,所以需要整片512字节的擦除写入。每次写入前,先把该片区的512字节读取到缓存中,再将需要修改的内容填充到缓存中,最后一次将512字节写入Flash片区

在这里插入图片描述

void Flash_SecureWrite(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)

{

int i=0;

u16 offsetAddr = WriteAddr%512;

u16 baseAddr = WriteAddr-offsetAddr;

FLASH_Read(baseAddr, tx_buf, 512);

for(i=0; i

{

tx_buf[offsetAddr+i] = pBuffer[i];

}

FLASH_Write(baseAddr, tx_buf, 512);

}


void FLASH_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)

{

char *Flash_ptr;                          // Flash pointer

unsigned int i;


Flash_ptr = (char *)WriteAddr;            // Initialize Flash pointer

FCTL3 = FWKEY;                            // Clear Lock bit

FCTL1 = FWKEY + ERASE;                    // Set Erase bit

*Flash_ptr = 0;                           // Dummy write to erase Flash seg


FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation


for (i = 0; i < NumToWrite; i++)

{

  *Flash_ptr++ = pBuffer[i];                   // Write value to flash

}


FCTL1 = FWKEY;                            // Clear WRT bit

FCTL3 = FWKEY + LOCK;                     // Set LOCK bit

}


void FLASH_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)

{

char *Flash_ptr;

u32 i;

Flash_ptr = (char *)ReadAddr;            // Initialize Flash pointer


for(i=0; i

pBuffer[i] = *Flash_ptr++;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

拷贝结束后,BOOT跳转到APP。

void Boot2App(void)

{

// u16 appAddr = 0xBFFE  ;// 0x1200

FLASH_Read(PROJECT_VERSION_ADDR,(u8 *)projectVersion,0x10);

FLASH_Read(FLASH_OTA_STATUS_ADDR,(u8 *)&isBoot,2);//App(0) or Boot(1)


if(isBoot==0)

{

if(strstr(projectVersion,"AquaDO"))

{

isBoot = 2;

delay_ms(1000);

rs485_send("Boot2Apprn",strlen("Boot2Apprn"));

asm(" mov &0xEFFE,PC;");

// asm(" mov #0xBFFE,PC;");

// asm(" mov #0x1200,PC;");

// asm(" br &0x1200;");

// asm(" LB 0x1200");

// ((void (*)(void))appAddr)();

}

}

}

关键字:CCS工程  MSP430  串口升级 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic492512.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:MSP430单片机定时器学习笔记
下一篇:MSP430教程15:MSP430单片机串行通讯模块

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

MSP430在CCS开发环境下的内存分配
这样的分析,我们很自然地想到,如果这些字符串常量能够离程序所在的区域“近一些”,那么这个问题就能解决了。如何来控制字符串常量所在的存储区域呢?这里我们需要了解一下cmd文件。以MSP430F6638的cmd文件为例,它主要包含了两个信息。一个是关于MSP430F6638的内存映射信息,如下图所示。利用红色的区域中的信息,我们也可以计算出,6638的RAM是从0x2400开始,大小为16K,USBRAM是从0x1c00开始,大小为2k,FLASH分为两个区域总的大小为256K。另一个是关于变量、代码等分配的存储位置。如下如所示。我们需要重点关注的是红色区域内的信息。观察一下。我们不难理解红色区域内代码的含义,是将.bss段、.data段
发表于 2020-03-09
MSP430在CCS开发环境下的内存分配
msp430g2553单片机学习心得
四年前学习的TI的Msp430g2553这款单片机,最近在整理学习记录的时候把当时的学习心得重新写下来。学习单片机最早是学习的51系列的,看的也是广为推崇的郭天祥郭老师的《十天学习单片机》,个人觉得单片机学习还是最先攻克51的。学习好51之后,对单片机操作有了基本的认识,再学习其他款单片机自然是能融会贯通。TI的430系列主打是低功耗,它的技术文档和Dome程序都非常详细,尤其是技术文档真让人有种膜拜的感觉,在每个模块的时候还有个框图,对理解模块内设置非常有帮助,我当时还特意打印了。当时它的User's Guide还没有中文版,如果实在看不懂,可以借鉴F149系列的(这款有人翻译了中文版本)。个人觉得在学习g2553这款
发表于 2020-03-09
学习MSP430G2553总结
个人感觉TI做的这块430就是一坨屎,内部时钟根本不稳,而且连datesheet都没有,但作为比赛指定的东西我们还是学了,这个连51都不如的16位单片机费了我四天时间把内部的模块给调了一遍,但是我调IIC时一直调不出来连时钟都没有,估计是做这块垃圾是连这个模块都没有吧,而且还写的那么复杂,连份像样的技术文档都没有,看的是别的技术文档,真是蛋疼无比,好了牢骚就发这么多,下面开始讲讲这块片子。首先介绍下MSP430G2553的时钟,这块芯片的时钟源是四个,时钟线是4个;时钟源我们就不说了,一般都是默认的选择内部的DCO作为时钟源,然后通过一系列的嫁接到MCLK SMCLK上,至于为什么这块芯片上不用锁相环的问题我深表不解,这个解释
发表于 2020-03-09
学习MSP430G2553总结
msp430 timerA interrupt
#include <msp430x24x.h> #define uchar unsigned char#define uint unsigned intuchar   table[16] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,                0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};uchar  position[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf
发表于 2020-03-09
MSP430:AD10
使用的MSP430G2553,为AD10,正常有8路输出,P1.0-P1.7为A0-A7有七个寄存器,参考电压可以是VCC或者内部参考电压1.5V或者2.5V参考时钟可以是内部ADC10OSC最高转换速率达200ksps转换方式四种:单通道单次,序列通道单次,单通道多次,序列通道多次。多次转换时候会用到DTC功能防止数据还没被取出就被覆盖单通道的实例程序,开启的为通道5,也就是P1.5 1 void AD_Channel5_Config(void) 2 { 3   /* Configure ADC  Channel */ 4   
发表于 2020-03-09
MSP430:AD10
MSP430低功耗设置小结
设置低功耗模式也就是对SR状态寄存器当中的位进行操作SCG0.SCG1,CPUOFF,OSCOFF等位进行操作如果我们要设置低功耗模式,那一般来说也是要设置 中断的,在中断函数中打开CPU来执行我们想要执行的程序大部分时间CPU是处于OFF状态的,这样可以达到降低功耗的目的void main{    unsigned char i;    BCSCTL1|=DIVA_2;    WDTCTL=_WDT_ADLY_1000;    IE1|=WTDIE;    while(1)    {    &
发表于 2020-03-09
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved