msp430芯片初探

N年前作的一个超级烂的msp430 并口仿真器,当时是msp430刚刚进入中国的时候做的,竟然让我在箱子里面翻了出来,我都佩服我自己了。

尽管仿真器看着烂,但是居然能用!

此外,在箱子里面找出了M年前参加msp430研讨会送的msp430f437手表,依稀还能看到“手表”的风采。

其中手表的原理图如下:

手表的有关介绍如下:

Watch Operation:

First Startup:

When initially powered, the device will display the default time:  12:00:00.  It will immediately begin counting the seconds.

Normal Operation:

Setting the Time (Minutes):  Press and hold SW1, pressing SW2 now increments the minute value.  

Setting the Time (Hours):  Press and hold SW2, pressing SW1 now increments the hour value. 

Note: When pressing SW2, the device will first appear to change the unit mode.  This is ignored by the watch after SW1 is pressed.

Displaying the Temperature:  Press SW1, watch will return to clock mode after 6 seconds

Changing the unit Mode:  Press and hold SW2

Switching off LCD: Press SW1 (to enter Temperature mode) Press SW1 again.  The LCD will turn on after 5 seconds.

Note: while LCD is off, device is in “low-power clock” mode and not in temperature mode.

Erasing Calibration Values:  Press and hold SW2 until the temperature is displayed.  While temperature is displayed, SW2 increases the displayed value and SW1 decreases the displayed value.  Holding SW1 and SW2 simultaneously for 1 second saves the calibrated value.

Note For Instructors:  The code running on the watch boards when shipped does not save temperature calibrations between power offs.  The C file available on the web does include this function as well as displaying 1degree F to indicate being un-calibrated.

 

标准msp430的JTAG接口如下:

编译程序安装的是IAR 4.201版本,选择里面的connection为softbaugh LPT(其他有关LPT的选项也是可以的)。

手上还有一个JLINK,赶明再尝试一下是否可以仿真。

付程序如下:

//******************************************************************************
//  430Day 2004 watch.c - Multi-function demo with Clock & Temperature
//
//
//  Murugavel Raju
//  Lane Westlund
//  Texas Instruments, Inc
//  January, 2004
//  Built with IAR Embedded Workbench Version: 2.21B
//  Modified by Albus 3/25/2004
//
//
//******************************************************************************

#include  <msp430x43x.h>

#define PB_TEMP (1 << 1)                // Push Button 1, Temperature: P2.1
#define PB_ALT  (1 << 2)                // Push Button 2, Alternate: P2.2
#define TEMP_COMPENSATION 16802 / 4096

typedef unsigned int word;              // Type definition for 'word'

enum
{
  ENGLISH,
  METRIC
};

static char *LCD = LCDMEM;
static int MODE_TIME = 5;
static int LCD_OFF_TIME = 5;

static int Refcal_ram = 1500;           // ADC12 1.5V reference calibration variable
static int Temp_slope_ram = 761;        // Temperature slope calibration variable
static int Temp_offset_ram = 469;       // Temperature offset calibration variable

int unitMode = ENGLISH;                 // The current state for measurements (metric/english)
static unsigned char seconds = 0, minutes = 0, hours = 0x12; // The default time values
int tempModeTime;                       // The number of seconds left to display the temperature
int lcdOffModeTime;                     // The number of seconds left to have the LCD off
int twoButtonsPressed;                  // The amount of time both buttons were pressed
signed int tempF;                       // Temperature variable
int held_down = 0;

void displayTime( void );               // Displays time
void displayValue( int value, int stop );// Displays an int value on the LCD.  Value can be moved in memory using the stop variable (in order to append metric characters to an int value)
void clearLCD(void);                    // Clears the LCD memory
void init(void);                        // Increments the hours variable (and rolls over to 12 if needed)
void decMinutes(void);
void incMinutes(void);
void incHours(void);
void displayTemp(void);                 // Gets the current temperature and displays it on the LCD
void changeUnitMode(void);              // Changes the units of measurement from English to Metric
void calibrate(void);                   // Calibrates the temperature
void getTemp(void);                     // Gets the current temperature
void flashLCD(void);

void flash_write(word* address, int data);// Write the (integer) data to the addressed flash
void flash_erase(word* address);        // Erase the addressed flash segment

//added the following SIX lines to declare variables in Flash INFO memory for IAR 2.x
#pragma dataseg=INFOA
__no_init static word Refcal_flash;     // ADC12 reference calibration in Flash INFO memory
__no_init static word Temp_slope;       // Temperature sensor slope calibration in Flash INFO memory
__no_init static word Temp_offset;      // Temperature sensor offset calibration in Flash INFO memory
#pragma dataseg=default

// LCD segment definitions.
#define d 0x80
#define c 0x40
#define b 0x20
#define a 0x10
#define h 0x08
#define e 0x04
#define g 0x02
#define f 0x01

const char char_gen[] = {
  a+b+c+d+e+f,                          // Displays "0"
  b+c,                                  // Displays "1"
  a+b+d+e+g,                            // Displays "2"
  a+b+c+d+g,                            // Displays "3"
  b+c+f+g,                              // Displays "4"
  a+c+d+f+g,                            // Displays "5"
  a+c+d+e+f+g,                          // Displays "6"
  a+b+c,                                // Displays "7"
  a+b+c+d+e+f+g,                        // Displays "8"
  a+b+c+d+f+g,                          // Displays "9"
  a+b+c+e+f+g,                          // Displays "A"
  0x00,                                 // Displays  Blank
  a+d+e+f,                              // Displays "C"
  a+b+f+g,                              // Displays "degrees" o
  a+d+e+f+g,                            // Displays "E"
  a+e+f+g,                              // Displays "F"  
  h,                                    // Displays ":" or "."
  g,                                    // Displays "-"
  f+g+e+d                               // Displays "t"                                                       
};


#undef a
#undef b
#undef c
#undef d
#undef e
#undef f
#undef g
#undef h

void main(void)
{
 
  init();
  clearLCD();                                         
   
  while( 1 )
  {
    LPM3;                               // Wait in LPM3 for the 1 second timer interrupt
    if( tempModeTime > 0 )              // Called if tempMode is the highest non-zero mode (temp was the most recent pushed)
    {
        LCDCTL |= LCDON;
        getTemp();
       
        if (tempF > 79)
          P1OUT |= 0x01;
        else
          P1OUT &= ~0x01;
         
        displayTemp();
        tempModeTime--;                 // Decrement the temp time counter (once a second)
    }
    else if( (~P2IN & (PB_ALT)) )       // if alt button held
    {
      P1OUT &= ~0x01;
      held_down++;
      if( held_down == 4 )
      {
        held_down = 0;

        unitMode ^= 1;                  // Toggle between 1 and 0
        calibrate();
       
      }
    }
    else                                // Default, display the time
    {                              
      P1OUT &= ~0x01;
      if(lcdOffModeTime == 0)
      {
        LCDCTL |= LCDON;
        displayTime();                             
        twoButtonsPressed = 0;
      }
      else{
        lcdOffModeTime--;
      }
    }
  }
}

int __low_level_init(void)
{

  FLL_CTL0 |= XCAP18PF;                 // Set load capacitance for xtal
  WDTCTL = WDTPW + WDTHOLD;             // Disable the Watchdog
  while(FLL_CTL0 & LFOF);               // Wait until LF OSC stabilizes
    
  return (1);                           // Flag to initialize the data segment
}

void init( void )
{
  P1OUT = 0x00;                         // P1.0 = LED
  P1DIR = 0xFF;
  P2OUT = 0x00;
  P2DIR = 0xF9;
  P3OUT = 0x00;
  P3DIR = 0xFF;
 
  P6OUT = 0x00;
  P6DIR = 0xFF;
   
  LCDCTL = LCDON + LCDSG0_3 + LCD4MUX;  // 4mux LCD, segs0-15 = outputs
   
  BTCTL = BT_fLCD_DIV128 + BTDIV + BTIP2 + BTIP1;// Set LCD frame freq = ACLK/128, set interrupt interval
  IE2 |= BTIE;                          // Enable Basic Timer interrupt
  P5SEL  = 0xFC;                        // Set Rxx and COM pins for LCD   
  clearLCD();
   
  P2DIR = ~(PB_TEMP + PB_ALT);          // Set ports to input for temperature and alternate switches
 
  P2IFG = 0;                            // Clear pending P2 interrupts
  P2IES = PB_TEMP + PB_ALT;             // Set interrupt to occur on high-to-low transition on switches
  P2IE = PB_TEMP + PB_ALT;              // Enable interrupts for switches
   
  FCTL2 ^= FXKEY + FN2 + FN1 + FN0;     // Set FLASH timing generator 447.5Khz                            
        
  ADC12CTL1 = SHP;                      // Pulse mode select for ADC12
  ADC12IE = BIT0;                       // Enable interrupts for ADC12
 
  Refcal_ram = Refcal_flash;            // Make RAM copy of Vref cal value
  Temp_slope_ram = Temp_slope;          // Make RAM copy of Temp slope value
  Temp_offset_ram = Temp_offset;        // Make RAM copy of Temp offset value
 
  _EINT();                                                        
}

void flashLCD(void)
{
  int i;
  TACTL = TASSEL0 + TACLR + MC1;        // TACLK = ACLK, 16-bit up-mode
  for( i = 0; i < 20; i++)
  {
    LCD[i] = 0xff;
  }
  for( i = 0 ; i < 7; i++)
  {
    LCDCTL |= LCDSON;
    CCR1 = 60000;                       // Delay
    CCTL1 = CCIE;                       // Compare-mode interrupt
    LPM3;                               // Wait for delay
  }
}

void calibrate()
{     
  _DINT();
   
  Refcal_ram = 1500;                    // Make RAM copy of Vref cal value
  Temp_slope_ram = 761;                 // Make RAM copy of Temp slope value
  Temp_offset_ram = 469;                // Make RAM copy of Temp offset value
       
  _EINT();
  getTemp();
  Temp_offset_ram += tempF - 75;        // Make default temp 75 (user will be near there)
   
  while( !((~P2IN & PB_TEMP) && (~P2IN & PB_ALT)))// Loop until user holds down both buttons
  {
   
    TACTL = TASSEL0 + TACLR + MC1;      // TACLK = ACLK, 16-bit up-mode.
    P2IE &= ~(PB_TEMP + PB_ALT);        // disable interrupts for switches
 
    if(~P2IN & PB_TEMP)
    {
      Temp_offset_ram++;
    }
    if(~P2IN & PB_ALT)
    {
      Temp_offset_ram--;
    }
    
    CCR1 = 10000;                       // Delay
    CCTL1 = CCIE;                       // Compare-mode interrupt
       
    LPM3;                               // Wait for delay
       
    getTemp();
    displayTemp();
  }
  while( (~P2IN & PB_TEMP) && (~P2IN & PB_ALT) ); // pause until user stops holding down buttons
  tempModeTime = 0;
  P2IFG = 0;
  P2IE |= PB_TEMP + PB_ALT;           // Enable interrupts for switches
 
  flash_erase((void *)&Refcal_flash);   // Erase Flash INFO segment A
  flash_write((void *)&Refcal_flash, Refcal_ram);// Write cal data to Refcal
  flash_write((void *)&Temp_offset, Temp_offset_ram);// Write offset data
  flash_write((void *)&Temp_slope, Temp_slope_ram);// Write slope data
 
  _EINT();                              // Re-enable general interrupts
 
  Refcal_ram = Refcal_flash;            // Make RAM copy of Vref cal value
  Temp_slope_ram = Temp_slope;          // Make RAM copy of Temp slope value
  Temp_offset_ram = Temp_offset;        // Make RAM copy of Temp offset value

}

void getTemp(void)
{
  ADC12CTL0 &= ~ENC;                    // Clear ENC first
  ADC12CTL0 = SHT0_15 + REFON + ADC12ON;
  ADC12MCTL0 = INCH_10 + SREF_1;        // Sample channel 10 using internal reference
  TACTL = TASSEL0 + TACLR + MC1;        // TACLK = ACLK, 16-bit up-mode
  CCR1 = 1500;                          // Delay to allow Ref to settle
  CCTL1 = CCIE;                         // Compare-mode interrupt
  LPM3;                                 // Wait for delay
  ADC12CTL0 |= ENC + ADC12SC;           // Start conversion
  LPM3;                                 // Wait for conversion completion
  ADC12CTL0 &= ~ENC;                    // Clear ENC first
  ADC12CTL0 = 0;                        // Turn-off ADC12
   
  tempF = (((long) ADC12MEM0 * Temp_slope_ram) / 4096 - Temp_offset_ram);
}

void displayTemp(void)
{
  clearLCD();
 
  if( unitMode == ENGLISH )
  {
    displayValue(tempF, 2);
    LCDM7 = char_gen[15];               // Display "F'
    LCDM6 = char_gen[13];               // Display degree
  }
  else
  {
    tempF -= 32;
    tempF *= .5555;                     // 5/9
       
    displayValue(tempF, 2);
    LCDM7 = char_gen[12];               // Display "C"
    LCDM6 = char_gen[13];               // Display degree
  }
}

void displayTime(void)
{
  LCDM7 = 0;
   
  LCDM6 = char_gen[seconds&0x0f];
  LCDM5 = char_gen[(seconds>>4)&0x0f]+char_gen[16];
   
  LCDM4 = char_gen[minutes&0x0f];
  LCDM3 = char_gen[(minutes>>4)&0x0f]+char_gen[16];
   
  LCDM2 = char_gen[hours&0x0f];
  if( hours & 0x10 )
  {
    LCDM1 = char_gen[1];
  }
  else
  {
    LCDM1 = 0;
  }
}

void displayValue( int value, int stop )
{
  int i;
  int sign = 0;
  if( value < 0 )
  {
    value = ~value +1;
    sign = 1;
  }
  i = 6-stop;
  while( value > 9 )
  {
    LCD[i] = char_gen[value%10];
    value = value/10;
    i--;
  }
  LCD[i] = char_gen[value];
  if( sign )
  {
    LCD[i-1] = char_gen[17];
  }
}

void incHours (void)
{   
  hours = __bcd_add_short(hours, 0x01);
 
  if (hours == 0x13)
    hours = 0x01;                       // If hrs transition is 12 to 13, hrs = 1

}

void incMinutes(void)
{   
  minutes = __bcd_add_short(minutes, 0x01);
  if (minutes == 0x60)
  {
    minutes = 0;
    incHours();
  } 
}

void decMinutes(void)
{
  if( (--minutes & 0x0f) == 0x0f )
  {
    minutes = (minutes & 0xf0)+0x09;
    if( minutes == 0xf9 )
    {
      minutes = 0x59;
      if( --hours == 0x00)
      {
        hours = 0x12;
      }
      else if( hours == 0x0f )
      {
        hours = 0x09;
      }
    }
  }

}


void clearLCD(void)
{
  int i;
  for( i = 0; i < 20; i++ ){
    LCD[i] = 0;
  }
}

void changeUnitMode(void)
{

  unitMode ^= 1;                        // Toggle between 1 and 0
  clearLCD();
  if(unitMode == METRIC)
  {
    LCDM7 = char_gen[12];               // Display degrees C for indication
    LCDM6 = char_gen[13];
  }
  else
  {
    LCDM7 = char_gen[15];               // Display degrees F for indication
    LCDM6 = char_gen[13];
  }
}


void flash_write(word* address, int data)// Write the (integer) data to the addressed flash
{
  word gie = _BIC_SR(GIE) & GIE;        // Disable interrupts

  FCTL3 = FWKEY;                        // Unlock the flash
  FCTL1 = FWKEY + WRT;                  // Enable flash write
  *address = data;                      // Write the data to the flash
  FCTL1 = FWKEY;                        // Disable flash write
  FCTL3 = FWKEY + LOCK;                 // Lock the flash
  _BIS_SR(gie);                         // Restore interrupts (to previous state)
}

void flash_erase(word* address)         // Erase the addressed flash segment
{
  word gie = _BIC_SR(GIE) & GIE;        // Disable interrupts
 
  FCTL3 = FWKEY;                        // Unlock the flash
  FCTL1 = FWKEY + ERASE;                // Enable flash segment erase
  *address = 0;                         // Erase the flash segment
  FCTL1 = FWKEY;                        // Disable flash segment erase
  FCTL3 = FWKEY + LOCK;                 // Lock the flash
  _BIS_SR(gie);                         // Restore interrupts (to previous state)
}

// Basic Timer interrupt service routine
#pragma vector=BASICTIMER_VECTOR
__interrupt void bt_isr(void)
{
  seconds = __bcd_add_short(seconds, 0x01);
  if( seconds == 0x60 )
  {
    seconds = 0;
    minutes = __bcd_add_short(minutes, 0x01);
    if( minutes == 0x60 )
    {
      minutes = 0;
      hours = __bcd_add_short(hours, 0x01);
      if( hours == 0x13 )
      {
        hours = 0x01;
      }
    }
  }

  LPM3_EXIT;                            // Exit LPM3 mode on return
}


#pragma vector=PORT2_VECTOR
__interrupt void p2_isr(void)
{ unsigned volatile int i;

  for (i = 0x3000; i>0 ; i--);          //Debounce
 
  if( (~P2IN & PB_TEMP)&&(P2IFG&PB_ALT) )//If temp button held, and alt button pressed...
  {
    incMinutes();
    tempModeTime = 0;
    displayTime();
    P1OUT &= ~0x01;
  }
  else if( (~P2IN & PB_ALT)&&(P2IFG&PB_TEMP) )//If alt button held, and temp button pressed...
  {

    unitMode ^= 1;                      // Toggle between 1 and 0
    incHours();
    displayTime();
    tempModeTime = 0;
    P1OUT &= ~0x01;
    held_down = 0;
  }
  else if ( tempModeTime > 0 && P2IFG & PB_TEMP ){
    LCDCTL &= ~LCDON;
    lcdOffModeTime = LCD_OFF_TIME;
    tempModeTime = 0;
  }
  else if( P2IFG & PB_TEMP )            // If temp button pressed, start displaying temp
  {        
    tempModeTime = MODE_TIME;
  }
 
  else if ( P2IFG & PB_ALT )            // If alt button pressed, toggle degrees C & F
  {       
    changeUnitMode();
  }
 
  P2IFG = 0;
}

#pragma vector=ADC_VECTOR
__interrupt void adc_isr(void)
{
  ADC12IFG &= ~BIT0;                    // Clear MEM0 interrupt flag
  LPM3_EXIT;                            // The ADC value is available in ADC12MEM0
}

enum
{
  NO_INT = 0,
  CC1_INT = 2,
  CC2_INT = 4,
  TA_INT = 10
};

#pragma vector=TIMERA1_VECTOR
__interrupt void ta1_isr(void)
{
  switch (TAIV)
  {
    case NO_INT: break;
    case CC1_INT: TACTL = 0; break;     // Disable TimerA
    case CC2_INT: break;
    case TA_INT: break;
    default: break;
  }
  LPM3_EXIT;                            // Exit LPM3 on return
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以太网MSP430开发板硬件特点: 1.使用 MSP430F149主MCU, 2K RAM, 60kflash, 48个I/O pin, 双uart 口, 8路12位A/D转换 2.TCP/IP接口采用 工业级CS8900芯片 全面支持uIP协议栈 3.带有USB通信接口,适合使用笔记本的同学进行调试。 4.主电路板带: uart 口DB9输出座; I2C EEPROM存储器AT24C256一块 也可以选择 搭配擦除寿命1亿次的同接口铁电存储器; 3.3V稳压集成电路采用高稳定度AS1117-3.3 数据口P4和所有多余I/O口引出,便于扩展 配有高频(HF)和低频(LF)两种晶振,可方便选择 各单元电路间有良好去耦合措施,采用大面积接地技术,电磁兼容性能良好 5.具有板载硬件实时钟PCF8563,并搭配电池,满足特定应用需要。 如截图所示: CS8900A的说明: CS8900、CS8900A芯片是Cirrus Logic公司生产的一种局域网处理芯片,在嵌入式领域中使用非常常见。它的封装是100-pin TQFP,内部集成了在片RAM、10BASE-T收发滤波器,并且提供8位和16位两种接口,一般在单片机中,使用了CS8900的8位接口模式。可选择1:1.414YL18-1064S或1:2.5 YL18-1080S 变压比例的变压器。 CS8900A网卡工作原理: CS8900A与ARM芯片按照16位方式连接,网卡芯片复位后默认工作方式为I/O连接,基址是300H。 最主要的工作寄存器(为16位),CS8900支持8位模式,当读或写16位数据时,低位字节对应偶地址,高位字节对应奇地址。例如,向TXCMD中写入00C0H,则可将00h写入305H,将C0H写入304H。 附件内容截图:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值