一、前文
第一次接触MSP430的芯片,第一次使用CCS开发环境,花了将近一个星期的时间,才把MSP430串口升级做出来。
同样分成BOOT(引导程序)、APP(主程序)、上位机(PC端工具),三个部分来讲解。
本博文是APP(主程序)相关讲解。
二、APP程序起始地址
- 在lnk_msp430fg479.cmd中修改APP Flash地址。
- FLASH改成0x1200(为啥不是0x1100呢,为了保证是512的整数,方便Flash写入)
- 中断向量往前挪
- 增加一个参数块,用来存放软件版本号(10字节)
- INFOA中存放系统配置信息
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 = 0x1200, length = 0xDDD0
PARAM : origin = 0xEFD0, length = 0x0010
INT00 : origin = 0xEFE0, length = 0x0002
INT01 : origin = 0xEFE2, length = 0x0002
INT02 : origin = 0xEFE4, length = 0x0002
INT03 : origin = 0xEFE6, length = 0x0002
INT04 : origin = 0xEFE8, length = 0x0002
INT05 : origin = 0xEFEA, length = 0x0002
INT06 : origin = 0xEFEC, length = 0x0002
INT07 : origin = 0xEFEE, length = 0x0002
INT08 : origin = 0xEFF0, length = 0x0002
INT09 : origin = 0xEFF2, length = 0x0002
INT10 : origin = 0xEFF4, length = 0x0002
INT11 : origin = 0xEFF6, length = 0x0002
INT12 : origin = 0xEFF8, length = 0x0002
INT13 : origin = 0xEFFA, length = 0x0002
INT14 : origin = 0xEFFC, length = 0x0002
RESET : origin = 0xEFFE, length = 0x0002
/* 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*/
}
SECTIONS
{
.bss : {} > RAM /* Global & static vars */
.data : {} > RAM /* Global & static vars */
.TI.noinit : {} > RAM /* For #pragma noinit */
.sysmem : {} > RAM /* Dynamic memory allocation area */
.stack : {} > RAM (HIGH) /* Software system stack */
.text : {} > FLASH /* Code */
.cinit : {} > FLASH /* Initialization tables */
.const : {} > FLASH /* Constant data */
.cio : {} > RAM /* C I/O Buffer */
.pinit : {} > FLASH /* C++ Constructor tables */
.binit : {} > FLASH /* Boot-time Initialization tables */
.init_array : {} > FLASH /* C++ Constructor tables */
.mspabi.exidx : {} > FLASH /* C++ Constructor tables */
.mspabi.extab : {} > FLASH /* C++ Constructor tables */
#ifdef __TI_COMPILER_VERSION__
#if __TI_COMPILER_VERSION__ >= 15009000
#ifndef __LARGE_DATA_MODEL__
.TI.ramfunc : {} load=FLASH, run=RAM, table(BINIT)
#else
.TI.ramfunc : {} load=FLASH | FLASH2, run=RAM, table(BINIT)
#endif
#endif
#endif
.infoA : {} > INFOA /* MSP430 INFO FLASH Memory segments */
.infoB : {} > INFOB
.infoC : {} > INFOC
.infoD : {} > INFOD
.param : {} > PARAM
/* MSP430 Interrupt vectors */
BASICTIMER : { * ( .int00 ) } > INT00 type = VECT_INIT
PORT2 : { * ( .int01 ) } > INT01 type = VECT_INIT
.int02 : {} > INT02
DAC12_DMA : { * ( .int03 ) } > INT03 type = VECT_INIT
PORT1 : { * ( .int04 ) } > INT04 type = VECT_INIT
TIMERA1 : { * ( .int05 ) } > INT05 type = VECT_INIT
TIMERA0 : { * ( .int06 ) } > INT06 type = VECT_INIT
SD16A : { * ( .int07 ) } > INT07 type = VECT_INIT
USCIAB0TX : { * ( .int08 ) } > INT08 type = VECT_INIT
USCIAB0RX : { * ( .int09 ) } > INT09 type = VECT_INIT
WDT : { * ( .int10 ) } > INT10 type = VECT_INIT
COMPARATORA : { * ( .int11 ) } > INT11 type = VECT_INIT
TIMERB1 : { * ( .int12 ) } > INT12 type = VECT_INIT
TIMERB0 : { * ( .int13 ) } > INT13 type = VECT_INIT
NMI : { * ( .int14 ) } > INT14 type = VECT_INIT
.reset : {} > RESET /* MSP430 Reset vector */
}
#pragma DATA_SECTION (projectVersion,".param")
const char projectVersion[0x10] = "AquaDO V2.0";
三、Flash读写
- 读写系统配置信息,存放在INFOA 0x1000地址中,该地址64字节,整块擦除和写入
sys.h
/*
* sys.h
*
* Created on: 2018年11月30日
* Author: weijian
*/
#ifndef SYS_H_
#define SYS_H_
#include "util.h"
typedef struct
{
u16 isApp;
u16 modbusAddr;
char devSN[0x10];
float a, b, c, t_k, t_b, t_0;
}SYS_SETTING;
extern SYS_SETTING sys_setting;
void sys_clk_init(void);
void sys_setting_load(void);
void sys_setting_save(void);
void FLASH_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite);
void FLASH_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead);
#endif /* SYS_H_ */
sys.c
/*
* sys.c
*
* Created on: 2018年11月30日
* Author: weijian
*/
#include <msp430.h>
#include <math.h>
#include "sys.h"
#include "cmd.h"
SYS_SETTING sys_setting;
void sys_clk_init(void)
{
volatile unsigned int i;
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
SCFI0 |= FN_8; // x2 DCO freq, 8MHz nominal DCO
SCFQCTL = SCFQ_4M; // (127+1) x 32768 x 2 = 7.99 Mhz
FLL_CTL0 |= DCOPLUS + XCAP18PF; // DCO+ set so freq= xtal x D x N+1
do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
for (i = 0x47FF; i > 0; i--); // Time for flag to set
}
while ((IFG1 & OFIFG)); // OSCFault flag still set?
sys_setting_load();
}
void sys_setting_load(void)
{
u8 is_save = 0;
FLASH_Read(0x1000,(u8 *)(&sys_setting),sizeof(sys_setting));
if(isnan(sys_setting.a))
{
sys_setting.a = 1;
is_save = 1;
}
if(isnan(sys_setting.b))
{
sys_setting.b = 1;
is_save = 1;
}
if(isnan(sys_setting.c))
{
sys_setting.c = 0;
is_save = 1;
}
if(isnan(sys_setting.t_k))
{
sys_setting.t_k = 1;
is_save = 1;
}
if(isnan(sys_setting.t_b))
{
sys_setting.t_b = 0;
is_save = 1;
}
if(isnan(sys_setting.t_0))
{
sys_setting.t_0 = 25;
is_save = 1;
}
if(sys_setting.modbusAddr==0xffff)
{
sys_setting.modbusAddr = 2;
is_save = 1;
}
if(is_save)
sys_setting_save();
}
void sys_setting_save(void)
{
FLASH_Write(0x1000,(u8 *)(&sys_setting),sizeof(sys_setting));
}
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<NumToRead; i++)
pBuffer[i] = *Flash_ptr++;
}
四、输出Hex文件
- 输出hex文件
五、Hex转Bin文件
- hex转bin文件
下载hex2bin.exe,将hex拖动到exe上,就会在hex2bin.exe的文件夹上生成一个bin文件,文件名与hex文件名相同