MSP430G2231控制数显游标卡尺,感兴趣的可以试一下哈~
(原文件名:1.jpg)
(原文件名:2.jpg)
(原文件名:3.png)
这是代码,供大家参考:
//*******************************************
// Running on Launchpad
// MSP430G2231
// ------------------
// /|| XIN|-
// | | |
// --|RST XOUT|-
// | |
// Vin+ -->|A1+ P1.2 |
// |A1- = VSS P1.0|-->LED
// | P1.1|-->TX RS232
// | P1.4|<--CLOCK CALIPER
// | P1.5|<--DATA CALIPER
//
//*******************************************
#include
int value = 0; // value received from caliper
unsigned char clock_ac
tive = 0; // any clock activity during last 32msec?
unsigned char ready_for_data = 0;// idle between clock burts, ready for next one
unsigned char bits_so_far = 0; // current bit count during value "assembly"
// how many CPU cycles between bits
#define Bitime 104 //9600 Baud, SMCLK=1MHz (1MHz/9600)=104
unsigned char BitCnt; // Bit count, used when transmitting byte
unsigned int TXByte; // Value sent over UART when Transmit() is called
#define LED BIT0 // LED on P1.0
#define TXPIN BIT1 // RS232 TX on P1.1
#define CLOCK BIT4 // Clock on P1.4
#define DATA BIT5 // Data on P1.5
void Transmit(void);
void main(void)
{
DCOCTL = 0x00; // Safe Flow
BCSCTL1 = CALBC1_1MHZ; // run at 1Mhz
DCOCTL = CALDCO_1MHZ;
//WDT as 32 ms interval counter. If no action on clock withing 32msec,
// we are ready to receive next "number"
WDTCTL = WDT_MDLY_32; // default timer 32 msec
IE1 |= WDTIE; // Enable WDT interrupt
P1DIR |= LED; // Set P1.0 to output direction
P1OUT |= LED; // LED ON, we'r ready
P1SEL |= TXPIN;
P1DIR |= TXPIN; // Set P1.1 to output direction
// Set up CLOCK input pin
P1DIR &= ~CLOCK; // sets input direction
P1OUT |= CLOCK; // pull-up is selected
P1REN |= CLOCK; // pull-up/pull-down enabled
P1IES &= ~CLOCK; // interupt triggered on low-to-high
P1IFG &= ~CLOCK; // reset interup flag to 0. needs to be reset on start
P1IE |= CLOCK; // interupt enabled for CLOCK
// Set up DATA input pin
P1DIR &= ~DATA; // sets input direction
P1OUT |= DATA; // pull-up is selected
P1REN |= DATA; // pull-up/pull-down enabled
P1IES &= ~DATA; // interupt triggered on low-to-high
P1IFG &= ~DATA; // reset interup flag to 0. nneds to be reset on start
P1IE &= ~DATA; // interupt disabled for DATA
// sending something over serial
while (1)
{
__bis_SR_register(LPM0_bits + GIE);
// after we went into low power mode, program counter is at this instruction
// (next one after where you entered LPM), but it's not moving until you enable active mode
// within main loop. That can be done with __bic_SR_register_on_exit(LPM0_bits) in ISR
_NOP();
// seding next value. value has been assambled by CLOCL interupt function
// value is 16 bit, TXByte should be 8, sending in two parts
TXByte = value >> 8; // first byte (most significant bits)
Transmit();
TXByte = value & 0xFF; // second byte (least significant)
Transmit();
P1OUT ^= LED; // blink LED
}
}
// Function Transmits Character from TXByte
void Transmit()
{
CCTL0 = OUT; // TXD Idle as Mark
TACTL = TASSEL_2 + MC_2; // SMCLK, continuous mode
BitCnt = 0xA; // Load Bit counter, 8 bits + ST/SP
CCR0 = TAR;
CCR0 += Bitime; // Set time till first bit
TXByte |= 0x100; // Add stop bit to TXByte (which is logical 1)
TXByte = TXByte << 1; // Add start bit (which is logical 0)
CCTL0 = CCIS0 + OUTMOD0 + CCIE; // Set signal, intial value, enable interrupts
while ( CCTL0 & CCIE ); // Wait for TX completion
TACTL = TASSEL_2; // SMCLK, timer off (for power consumption)
}
// Timer A0 interrupt service routine. Used to send bits over RS232
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
CCR0 += Bitime; // Add Offset to CCR0
if ( BitCnt == 0) // If all bits TXed, disable interrupt
CCTL0 &= ~ CCIE;
else
{
CCTL0 |= OUTMOD2; // TX Space
if (TXByte & 0x01)
CCTL0 &= ~ OUTMOD2; // TX Mark
TXByte = TXByte >> 1;
BitCnt --;
}
}
// Button is pressed
#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{
static unsigned char port;
port = P1IN; // read DATA port value as soon as possible (otherwise it might be gone)
P1IFG &= ~CLOCK; // Clear interrupt flag
clock_active = 1;
if (ready_for_data)
{
if (bits_so_far && bits_so_far <= 16){ // first bit is start bit, ignore it. Total we have 24 bits. But we need only 16
if (!(port & DATA)) // if 0 recived, invert = >1
value |=0x8000; // then set most significant bit
value = value >> 1; // and move it one right
}else if (bits_so_far == 21){ // 21st bit indicates sighn (+/-)
if (!(port & DATA))
value = (~value)+1; // make it negative
}else if (bits_so_far >= 23){ // we'r done, got all bits
ready_for_data = 0; // warchdog timer will set it
__bic_SR_register_on_exit(LPM0_bits); // wake up main from LPM sleep
}
bits_so_far++;
}
}
// watchdog used as 30msec timer for detecting start of new bit burst on clock
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
if (ready_for_data)
return;
if (clock_active){
clock_active = 0; // clear flag, will wait another 32msec to see if there have been any activity of clock
ready_for_data = 0; // not yet ready
}else{
ready_for_data = 1; // nothing within last 32msec, ready for next clock burst
value = 0; // init of value
bits_so_far = 0; // init of bit counter
}
}