EZ430 Chronos 自带程序源码:高度计(气压计)示范程序

EZ430 Chronos 自带程序源码:高度计(气压计)示范程序
共4个文件:
1、altitude.c
2、altitude.h
3、vti_ps.c
4、vti_ps.h

altitude.c

// *************************************************************************************************
//
//	Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ 
//	 
//	 
//	  Redistribution and use in source and binary forms, with or without 
//	  modification, are permitted provided that the following conditions 
//	  are met:
//	
//	    Redistributions of source code must retain the above copyright 
//	    notice, this list of conditions and the following disclaimer.
//	 
//	    Redistributions in binary form must reproduce the above copyright
//	    notice, this list of conditions and the following disclaimer in the 
//	    documentation and/or other materials provided with the   
//	    distribution.
//	 
//	    Neither the name of Texas Instruments Incorporated nor the names of
//	    its contributors may be used to endorse or promote products derived
//	    from this software without specific prior written permission.
//	
//	  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
//	  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
//	  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
//	  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
//	  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
//	  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
//	  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//	  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//	  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
//	  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
//	  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// *************************************************************************************************
// Altitude measurement functions.
// *************************************************************************************************


// *************************************************************************************************
// Include section

// system
#include "project.h"

// driver
#include "altitude.h"
#include "display.h"
#include "vti_ps.h"
#include "ports.h"
#include "timer.h"

// logic
#include "user.h"


// *************************************************************************************************
// Prototypes section


// *************************************************************************************************
// Defines section


// *************************************************************************************************
// Global Variable section
struct alt sAlt;


// *************************************************************************************************
// Extern section

// Global flag for pressure sensor initialisation status
extern u8 ps_ok;


// *************************************************************************************************
// @fn          reset_altitude_measurement
// @brief       Reset altitude measurement.
// @param       none
// @return      none
// *************************************************************************************************
void reset_altitude_measurement(void)
{
	// Menu item is not visible
	sAlt.state 		= MENU_ITEM_NOT_VISIBLE;

	// Clear timeout counter
	sAlt.timeout	= 0;
	
	// Set default altitude value
	sAlt.altitude		= 0;
	
	// Pressure sensor ok?
	if (ps_ok)
	{
		// Initialise pressure table
		init_pressure_table();
		
		// Do single conversion
		start_altitude_measurement();
		stop_altitude_measurement();	

		// Apply calibration offset and recalculate pressure table
		if (sAlt.altitude_offset != 0)
		{
			sAlt.altitude += sAlt.altitude_offset;
			update_pressure_table(sAlt.altitude, sAlt.pressure, sAlt.temperature);
		}
	}
}


// *************************************************************************************************
// @fn          conv_m_to_ft
// @brief       Convert meters to feet
// @param       u16 m		Meters
// @return      u16		Feet
// *************************************************************************************************
s16 convert_m_to_ft(s16 m)
{
	return (((s32)328*m)/100);
}


// *************************************************************************************************
// @fn          conv_ft_to_m
// @brief       Convert feet to meters
// @param       u16 ft		Feet
// @return      u16		Meters
// *************************************************************************************************
s16 convert_ft_to_m(s16 ft)
{
	return (((s32)ft*61)/200);
}


// *************************************************************************************************
// @fn          is_altitude_measurement
// @brief       Altitude measurement check
// @param       none
// @return      u8		1=Measurement ongoing, 0=measurement off
// *************************************************************************************************
u8 is_altitude_measurement(void)
{
	return ((sAlt.state == MENU_ITEM_VISIBLE) && (sAlt.timeout > 0));
}


// *************************************************************************************************
// @fn          start_altitude_measurement
// @brief       Start altitude measurement
// @param       none
// @return      none
// *************************************************************************************************
void start_altitude_measurement(void)
{
	// Show warning if pressure sensor was not initialised properly
	if (!ps_ok) 
	{
		display_chars(LCD_SEG_L1_2_0, (u8*)"ERR", SEG_ON);
		return;
	}

	// Start altitude measurement if timeout has elapsed
	if (sAlt.timeout == 0)
	{
		// Enable DRDY IRQ on rising edge
		PS_INT_IFG &= ~PS_INT_PIN;
		PS_INT_IE |= PS_INT_PIN;

		// Start pressure sensor
		ps_start(); 

		// Set timeout counter only if sensor status was OK
		sAlt.timeout = ALTITUDE_MEASUREMENT_TIMEOUT;

		// Get updated altitude
		while((PS_INT_IN & PS_INT_PIN) == 0); 
		do_altitude_measurement(FILTER_OFF);
	}
}


// *************************************************************************************************
// @fn          stop_altitude_measurement
// @brief       Stop altitude measurement
// @param       none
// @return      none
// *************************************************************************************************
void stop_altitude_measurement(void)
{
	// Return if pressure sensor was not initialised properly
	if (!ps_ok) return;
	
	// Stop pressure sensor
	ps_stop();
	
	// Disable DRDY IRQ
	PS_INT_IE  &= ~PS_INT_PIN;
	PS_INT_IFG &= ~PS_INT_PIN;
	
	// Clear timeout counter
	sAlt.timeout = 0;
}



// *************************************************************************************************
// @fn          do_altitude_measurement
// @brief       Perform single altitude measurement
// @param       none
// @return       none
// *************************************************************************************************
void do_altitude_measurement(u8 filter)
{
	volatile u32 pressure;

	// If sensor is not ready, skip data read	
	if ((PS_INT_IN & PS_INT_PIN) == 0) return;
		
	// Get temperature (format is *10癒) from sensor
	sAlt.temperature = ps_get_temp();

	// Get pressure (format is 1Pa) from sensor
	pressure = ps_get_pa();	
		
	// Store measured pressure value
	if (filter == FILTER_OFF) //sAlt.pressure == 0) 
	{
		sAlt.pressure = pressure;
	}
	else
	{
		// Filter current pressure
		pressure = (u32)((pressure * 0.2) + (sAlt.pressure * 0.8));
	
		// Store average pressure
		sAlt.pressure = pressure;
	}
	
	// Convert pressure (Pa) and temperature (癒) to altitude (m)
	sAlt.altitude = conv_pa_to_meter(sAlt.pressure, sAlt.temperature);
}


// *************************************************************************************************
// @fn          sx_altitude
// @brief       Altitude direct function. Sx restarts altitude measurement.
// @param       u8 line	LINE1, LINE2
// @return      none
// *************************************************************************************************
void sx_altitude(u8 line)
{
	// Function can be empty
	
	// Restarting of altitude measurement will be done by subsequent full display update 
}


// *************************************************************************************************
// @fn          mx_altitude
// @brief       Mx button handler to set the altitude offset. 
// @param       u8 line		LINE1
// @return      none
// *************************************************************************************************
void mx_altitude(u8 line)
{
	s32 altitude;
	s32	limit_high, limit_low;

	// Clear display
	clear_display_all();

	// Set lower and upper limits for offset correction
	if (sys.flag.use_metric_units)
	{
		// Display "m" symbol
		display_symbol(LCD_UNIT_L1_M, SEG_ON);

		// Convert global variable to local variable
		altitude  = sAlt.altitude; 

		// Limits for set_value function
		limit_low = -100;
		limit_high = 4000;
	}
	else // English units
	{
		// Display "ft" symbol
		display_symbol(LCD_UNIT_L1_FT, SEG_ON);
		
		// Convert altitude in meters to feet
		altitude = sAlt.altitude;

 		// Convert from meters to feet
		altitude = convert_m_to_ft(altitude);		

		// Limits for set_value function
		limit_low = -500;
		limit_high = 9999;
	}

	// Loop values until all are set or user breaks	set
	while(1) 
	{
		// Idle timeout: exit without saving 
		if (sys.flag.idle_timeout) break;

		// Button STAR (short): save, then exit 
		if (button.flag.star) 
		{
			// When using English units, convert ft back to m before updating pressure table
			if (!sys.flag.use_metric_units) altitude = convert_ft_to_m((s16)altitude);

			// Update pressure table
			update_pressure_table((s16)altitude, sAlt.pressure, sAlt.temperature);
			
			// Set display update flag
			display.flag.line1_full_update = 1;

			break;
		}

		// Set current altitude - offset is set when leaving function
		set_value(&altitude, 4, 3, limit_low, limit_high, SETVALUE_DISPLAY_VALUE + SETVALUE_FAST_MODE + SETVALUE_DISPLAY_ARROWS, LCD_SEG_L1_3_0, display_value1);
	}		
	
	// Clear button flags
	button.all_flags = 0;
}


// *************************************************************************************************
// @fn          display_altitude
// @brief       Display routine. Supports display in meters and feet. 
// @param       u8 line			LINE1
//				u8 update		DISPLAY_LINE_UPDATE_FULL, DISPLAY_LINE_UPDATE_PARTIAL, DISPLAY_LINE_CLEAR
// @return      none
// *************************************************************************************************
void display_altitude(u8 line, u8 update)
{
	u8 * str;
	s16 ft;
	
	// redraw whole screen
	if (update == DISPLAY_LINE_UPDATE_FULL)	
	{
		// Enable pressure measurement
		sAlt.state = MENU_ITEM_VISIBLE;

		// Start measurement
		start_altitude_measurement();
		
		if (sys.flag.use_metric_units)
		{
			// Display "m" symbol
			display_symbol(LCD_UNIT_L1_M, SEG_ON);
		}
		else
		{
			// Display "ft" symbol
			display_symbol(LCD_UNIT_L1_FT, SEG_ON);
		}
		
		// Display altitude
		display_altitude(LINE1, DISPLAY_LINE_UPDATE_PARTIAL);
	}
	else if (update == DISPLAY_LINE_UPDATE_PARTIAL)
	{
		// Update display only while measurement is active
		if (sAlt.timeout > 0)
		{
			if (sys.flag.use_metric_units)
			{
				// Display altitude in xxxx m format, allow 3 leading blank digits
				if (sAlt.altitude >= 0)
				{
					str = itoa(sAlt.altitude, 4, 3);
					display_symbol(LCD_SYMB_ARROW_UP, SEG_ON);
					display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
				}
				else
				{
					str = itoa(sAlt.altitude*(-1), 4, 3);
					display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
					display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON);
				}
			}
			else
			{
				// Convert from meters to feet
				ft = convert_m_to_ft(sAlt.altitude);
				
				// Limit to 9999ft (3047m)
				if (ft > 9999) ft = 9999;
				
				// Display altitude in xxxx ft format, allow 3 leading blank digits
				if (ft >= 0)
				{
					str = itoa(ft, 4, 3);
					display_symbol(LCD_SYMB_ARROW_UP, SEG_ON);
					display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
				}
				else
				{
					str = itoa(ft*(-1), 4, 3);
					display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
					display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON);
				}				
			}
			display_chars(LCD_SEG_L1_3_0, str, SEG_ON);
		}
	}
	else if (update == DISPLAY_LINE_CLEAR)
	{
		// Disable pressure measurement
		sAlt.state = MENU_ITEM_NOT_VISIBLE;

		// Stop measurement
		stop_altitude_measurement();
		
		// Clean up function-specific segments before leaving function
		display_symbol(LCD_UNIT_L1_M, SEG_OFF);
		display_symbol(LCD_UNIT_L1_FT, SEG_OFF);
		display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
		display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
	}
}


altitude.h

// *************************************************************************************************
//
//	Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ 
//	 
//	 
//	  Redistribution and use in source and binary forms, with or without 
//	  modification, are permitted provided that the following conditions 
//	  are met:
//	
//	    Redistributions of source code must retain the above copyright 
//	    notice, this list of conditions and the following disclaimer.
//	 
//	    Redistributions in binary form must reproduce the above copyright
//	    notice, this list of conditions and the following disclaimer in the 
//	    documentation and/or other materials provided with the   
//	    distribution.
//	 
//	    Neither the name of Texas Instruments Incorporated nor the names of
//	    its contributors may be used to endorse or promote products derived
//	    from this software without specific prior written permission.
//	
//	  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
//	  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
//	  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
//	  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
//	  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
//	  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
//	  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//	  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//	  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
//	  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
//	  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// *************************************************************************************************

#ifndef ALTITUDE_H_
#define ALTITUDE_H_


// *************************************************************************************************
// Include section


// *************************************************************************************************
// Prototypes section
extern void reset_altitude_measurement(void);
extern u8 is_altitude_measurement(void);
extern void start_altitude_measurement(void);
extern void stop_altitude_measurement(void);
extern void do_altitude_measurement(u8 filter);

// menu functions
extern void sx_altitude(u8 line);
extern void mx_altitude(u8 line);
extern void display_altitude(u8 line, u8 update);


// *************************************************************************************************
// Defines section

// Stop altitude measurement after 60 minutes to save battery
#define ALTITUDE_MEASUREMENT_TIMEOUT	(60*60u)


// *************************************************************************************************
// Global Variable section
struct alt
{
	// MENU_ITEM_NOT_VISIBLE, MENU_ITEM_VISIBLE   
	menu_t	state; 

	// Pressure (Pa)
	u32		pressure;

	// Temperature (癒)
	u16		temperature;

	// Altitude (m)
	s16		altitude;
	
	// Altitude offset stored during calibration
	s16		altitude_offset;

	// Timeout
	u16		timeout;
};
extern struct alt sAlt;


// *************************************************************************************************
// Extern section


#endif /*ALTITUDE_H_*/

vti_ps.c

// *************************************************************************************************
//
//	Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ 
//	 
//	 
//	  Redistribution and use in source and binary forms, with or without 
//	  modification, are permitted provided that the following conditions 
//	  are met:
//	
//	    Redistributions of source code must retain the above copyright 
//	    notice, this list of conditions and the following disclaimer.
//	 
//	    Redistributions in binary form must reproduce the above copyright
//	    notice, this list of conditions and the following disclaimer in the 
//	    documentation and/or other materials provided with the   
//	    distribution.
//	 
//	    Neither the name of Texas Instruments Incorporated nor the names of
//	    its contributors may be used to endorse or promote products derived
//	    from this software without specific prior written permission.
//	
//	  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
//	  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
//	  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
//	  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
//	  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
//	  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
//	  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//	  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//	  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
//	  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
//	  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// *************************************************************************************************
// VTI SCP1000-D0x pressure sensor driver functions
// *************************************************************************************************


// *************************************************************************************************
// Include section

// system
#include "project.h"

// driver
#include "vti_ps.h"
#include "timer.h"


// *************************************************************************************************
// Prototypes section
u16 ps_read_register(u8 address, u8 mode);
u8 ps_write_register(u8 address, u8 data);
u8 ps_twi_read(u8 ack);
void twi_delay(void);


// *************************************************************************************************
// Defines section


// *************************************************************************************************
// Global Variable section

// VTI pressure (hPa) to altitude (m) conversion tables
const s16 h0[17] = { -153, 0, 111, 540, 989, 1457, 1949, 2466, 3012, 3591, 4206, 4865, 5574, 6344, 7185, 8117, 9164 };
const u16 p0[17] = { 1031, 1013, 1000, 950, 900, 850, 800, 750, 700, 650, 600, 550, 500, 450, 400, 350, 300 };
float p[17];

// Global flag for proper pressure sensor operation
u8 ps_ok;


// *************************************************************************************************
// Extern section



// *************************************************************************************************
// @fn          ps_init
// @brief       Init pressure sensor I/O
// @param       none
// @return      none
// *************************************************************************************************
void ps_init(void)
{
	volatile u8 success, status, eeprom, timeout;
	
	PS_INT_DIR &= ~PS_INT_PIN;            	// DRDY is input
	PS_INT_IES &= ~PS_INT_PIN;				// Interrupt on DRDY rising edge
	PS_TWI_OUT |= PS_SCL_PIN + PS_SDA_PIN; 	// SCL and SDA are outputs by default
	PS_TWI_DIR |= PS_SCL_PIN + PS_SDA_PIN; 	// SCL and SDA are outputs by default
	
	// Reset global ps_ok flag
	ps_ok = 0;

	// 100msec delay to allow VDD stabilisation
	Timer0_A4_Delay(CONV_MS_TO_TICKS(100));

	// Reset pressure sensor -> powerdown sensor
	success = ps_write_register(0x06, 0x01);   

	// 100msec delay 
	Timer0_A4_Delay(CONV_MS_TO_TICKS(100));

	// Check if STATUS register BIT0 is cleared
	status = ps_read_register(0x07, PS_TWI_8BIT_ACCESS);
	if (((status & BIT0) == 0) && (status != 0)) 
	{
		// Check EEPROM checksum in DATARD8 register 
		eeprom = ps_read_register(0x7F, PS_TWI_8BIT_ACCESS);
		if (eeprom == 0x01) ps_ok = 1;
		else 				ps_ok = 0;
	}
}


// *************************************************************************************************
// @fn          ps_start
// @brief       Init pressure sensor registers and start sampling
// @param       none
// @return      u8		1=Sensor started, 0=Sensor did not start
// *************************************************************************************************
void ps_start(void)
{
	// Start sampling data in ultra low power mode 
	ps_write_register(0x03, 0x0B);  
}



// *************************************************************************************************
// @fn          ps_stop
// @brief       Power down pressure sensor
// @param       none
// @return      none
// *************************************************************************************************
void ps_stop(void)
{
	// Put sensor to standby
	ps_write_register(0x03, 0x00);   
}



// *************************************************************************************************
// @fn          ps_twi_sda
// @brief       Control SDA line
// @param       u8 condition		PS_TWI_SEND_START, PS_TWI_SEND_RESTART, PS_TWI_SEND_STOP
//										PS_TWI_CHECK_ACK
// @return      u8					1=ACK, 0=NACK
// *************************************************************************************************
u8 ps_twi_sda(u8 condition)
{
	u8 sda = 0;
	
	if (condition == PS_TWI_SEND_START)
	{
		PS_TWI_SDA_OUT;			// SDA is output
		PS_TWI_SCL_HI;
		twi_delay();
		PS_TWI_SDA_LO;
		twi_delay();
		PS_TWI_SCL_LO;			// SCL 1-0 transition while SDA=0
		twi_delay();
	}
	else if (condition == PS_TWI_SEND_RESTART)
	{
		PS_TWI_SDA_OUT;			// SDA is output
		PS_TWI_SCL_LO;
		PS_TWI_SDA_HI;
		twi_delay();
		PS_TWI_SCL_HI;
		twi_delay();
		PS_TWI_SDA_LO;
		twi_delay();
		PS_TWI_SCL_LO;
		twi_delay();
	}
	else if (condition == PS_TWI_SEND_STOP)
	{
		PS_TWI_SDA_OUT;			// SDA is output
		PS_TWI_SDA_LO;
		twi_delay();
		PS_TWI_SCL_LO;		
		twi_delay();
		PS_TWI_SCL_HI;			
		twi_delay();
		PS_TWI_SDA_HI;			// SDA 0-1 transition while SCL=1
		twi_delay();
	}
	else if (condition == PS_TWI_CHECK_ACK)
	{
		PS_TWI_SDA_IN;			// SDA is input
		PS_TWI_SCL_LO;		
		twi_delay();
		PS_TWI_SCL_HI;			
		twi_delay();
		sda = PS_TWI_IN & PS_SDA_PIN;
		PS_TWI_SCL_LO;			
	}
	
	// Return value will only be evaluated when checking device ACK
	return (sda == 0);
}



// *************************************************************************************************
// @fn          twi_delay
// @brief       Delay between TWI signal edges. 
// @param       none
// @return      none
// *************************************************************************************************
void twi_delay(void)
{
	asm("	nop");
}


// *************************************************************************************************
// @fn          ps_twi_write
// @brief       Clock out bits through SDA.
// @param       u8 data		Byte to send
// @return      none
// *************************************************************************************************
void ps_twi_write(u8 data)
{
	u8 i, mask;
	
	// Set mask byte to 10000000b
	mask = BIT0<<7;
	
	PS_TWI_SDA_OUT;		// SDA is output
	
	for (i=8; i>0; i--)
	{
		PS_TWI_SCL_LO;	// SCL=0
		if ((data & mask) == mask)
		{
			PS_TWI_SDA_HI; // SDA=1
		}
		else 								
		{
			PS_TWI_SDA_LO; // SDA=0 
		}
		mask = mask >> 1;
		twi_delay();
		PS_TWI_SCL_HI;	// SCL=1
		twi_delay();
	}
	
	PS_TWI_SCL_LO;		// SCL=0
	PS_TWI_SDA_IN;		// SDA is input
} 


// *************************************************************************************************
// @fn          ps_twi_read
// @brief       Read bits from SDA
// @param       u8 ack		1=Send ACK after read, 0=Send NACK after read
// @return      u8			Bits read
// *************************************************************************************************
u8 ps_twi_read(u8 ack)
{
	u8 i;
	u8 data = 0;
	
	PS_TWI_SDA_IN;		// SDA is input
	
	for (i=0; i<8; i++)
	{
		PS_TWI_SCL_LO;			// SCL=0
		twi_delay();
		PS_TWI_SCL_HI;			// SCL=0
		twi_delay();
		
		// Shift captured bits to left 
		data = data << 1; 

		// Capture new bit
		if ((PS_TWI_IN & PS_SDA_PIN) == PS_SDA_PIN) data |= BIT0; 
	}

	PS_TWI_SDA_OUT;			// SDA is output
	
	// 1 aditional clock phase to generate master ACK
	PS_TWI_SCL_LO;			// SCL=0
	if (ack == 1)	PS_TWI_SDA_LO		// Send ack -> continue read
	else			PS_TWI_SDA_HI		// Send nack -> stop read
	twi_delay();
	PS_TWI_SCL_HI;			// SCL=0
	twi_delay();
	PS_TWI_SCL_LO;
	
	return (data);
} 



// *************************************************************************************************
// @fn          as_write_register
// @brief  		Write a byte to the pressure sensor
// @param       u8 address			Register address
//				u8 data			Data to write
// @return      u8					
// *************************************************************************************************
u8 ps_write_register(u8 address, u8 data)
{
  volatile u8 success;

  ps_twi_sda(PS_TWI_SEND_START);			// Generate start condition
  
  ps_twi_write((0x11<<1) | PS_TWI_WRITE); 	// Send 7bit device address 0x11 + write bit '0'
  success = ps_twi_sda(PS_TWI_CHECK_ACK);	// Check ACK from device
  if (!success) return (0);
  
  ps_twi_write(address);					// Send 8bit register address
  success = ps_twi_sda(PS_TWI_CHECK_ACK);	// Check ACK from device
  if (!success) return (0);
	
  ps_twi_write(data);						// Send 8bit data to register
  success = ps_twi_sda(PS_TWI_CHECK_ACK);	// Check ACK from device
 // Slave does not send this ACK
 // if (!success) return (0);
  
  ps_twi_sda(PS_TWI_SEND_STOP);				// Generate stop condition

  return (1);
}


// *************************************************************************************************
// @fn          ps_read_register
// @brief       Read a byte from the pressure sensor
// @param       u8 address		Register address
//				u8	mode		PS_TWI_8BIT_ACCESS, PS_TWI_16BIT_ACCESS
// @return      u16			Register content
// *************************************************************************************************
u16 ps_read_register(u8 address, u8 mode)
{
  u8 success;
  u16 data = 0;

  ps_twi_sda(PS_TWI_SEND_START);			// Generate start condition

  ps_twi_write((0x11<<1) | PS_TWI_WRITE); 	// Send 7bit device address 0x11 + write bit '0'
  success = ps_twi_sda(PS_TWI_CHECK_ACK);	// Check ACK from device
  if (!success) return (0);
  
  ps_twi_write(address);					// Send 8bit register address
  success = ps_twi_sda(PS_TWI_CHECK_ACK);	// Check ACK from device
  if (!success) return (0);

  ps_twi_sda(PS_TWI_SEND_RESTART);			// Generate restart condition

  ps_twi_write((0x11<<1) | PS_TWI_READ); 	// Send 7bit device address 0x11 + read bit '1'
  success = ps_twi_sda(PS_TWI_CHECK_ACK);	// Check ACK from device
  if (!success) return (0);
	
  if (mode == PS_TWI_16BIT_ACCESS)
  {
	  data =  ps_twi_read(1) << 8;			// Read MSB 8bit data from register
	  data |= ps_twi_read(0);				// Read LSB 8bit data from register
  }
  else
  {
	  data = ps_twi_read(0);				// Read 8bit data from register
  }  
  
  ps_twi_sda(PS_TWI_SEND_STOP);				// Generate stop condition

  return (data);
}



// *************************************************************************************************
// @fn          ps_get_pa
// @brief       Read out pressure. Format is Pa. Range is 30000 .. 120000 Pa.
// @param       none
// @return      u32		15-bit pressure sensor value (Pa)
// *************************************************************************************************
u32 ps_get_pa(void)
{
	volatile u32 data = 0;
	
	// Get 3 MSB from DATARD8 register
	data = ps_read_register(0x7F, PS_TWI_8BIT_ACCESS);
	data = ((data & 0x07) << 8) << 8;

	// Get 16 LSB from DATARD16 register
	data |= ps_read_register(0x80, PS_TWI_16BIT_ACCESS);
	
	// Convert decimal value to Pa
	data = (data >> 2);
	
	return (data);
}


// *************************************************************************************************
// @fn          ps_get_temp
// @brief       Read out temperature.
// @param       none
// @return      u16		13-bit temperature value in xx.x癒 format
// *************************************************************************************************
u16 ps_get_temp(void)
{
	volatile u16 data = 0;
	u16 temp = 0;
	u8 is_negative = 0;
	u16 kelvin;
	
	// Get 13 bit from TEMPOUT register
	data = ps_read_register(0x81, PS_TWI_16BIT_ACCESS);
	
	// Convert negative temperatures
	if ((data & BIT(13)) == BIT(13)) 
	{
		// Sign extend temperature
		data |= 0xC000;
		// Convert two's complement
		data = ~data;
		data += 1;
		is_negative = 1;
	}

	temp = data / 2;
	
	// Convert from 癈 to 癒
	if (is_negative)	kelvin = 2732 - temp;
	else				kelvin = temp + 2732;
	
	return (kelvin);
}


// *************************************************************************************************
// @fn          init_pressure_table
// @brief       Init pressure table with constants
// @param       u32		p 		Pressure (Pa)
// @return      u16				Altitude (m)
// *************************************************************************************************
void init_pressure_table(void)
{
	u8 i;

	for (i=0; i<17; i++) p[i] = p0[i];
}


// *************************************************************************************************
// @fn          update_pressure_table
// @brief       Calculate pressure table for reference altitude.
//				Implemented straight from VTI reference code.
// @param       s16		href	Reference height
//				u32		p_meas	Pressure (Pa)
//				u16		t_meas	Temperature (10*癒)
// @return     	none
// *************************************************************************************************
void update_pressure_table(s16 href, u32 p_meas, u16 t_meas)
{
	const float Invt00 = 0.003470415;
	const float coefp  = 0.00006;
	volatile float p_fact; 
	volatile float p_noll;
	volatile float hnoll;
	volatile float h_low = 0;
	volatile float t0;
	u8 i;
	
	// Typecast arguments
	volatile float fl_href 		= href;
	volatile float fl_p_meas 	= (float)p_meas/100;	// Convert from Pa to hPa
	volatile float fl_t_meas	= (float)t_meas/10;		// Convert from 10癒 to 1癒

	t0 = fl_t_meas + (0.0065*fl_href);
	
	hnoll  = fl_href/(t0*Invt00);
	
	for (i=0; i<=15; i++)
	{
		if (h0[i] > hnoll) break;
		h_low = h0[i];	
	}
	
	p_noll = (float)(hnoll - h_low)*(1 - (hnoll - (float)h0[i])* coefp)*((float)p0[i] - (float)p0[i-1])/((float)h0[i] - h_low) + (float)p0[i-1];

	// Calculate multiplicator
	p_fact = fl_p_meas/p_noll;
	
	// Apply correction factor to pressure table
	for (i=0; i<=16; i++)
	{
		p[i] = p0[i]*p_fact;	
	}
}


// *************************************************************************************************
// @fn          conv_pa_to_meter
// @brief       Convert pressure (Pa) to altitude (m) using a conversion table
//				Implemented straight from VTI reference code.
// @param       u32		p_meas	Pressure (Pa)
//				u16		t_meas	Temperature (10*癒)
// @return      s16				Altitude (m)
// *************************************************************************************************
s16 conv_pa_to_meter(u32 p_meas, u16 t_meas)
{
	const float coef2  = 0.0007;
	const float Invt00 = 0.003470415;
	volatile float hnoll;
	volatile float t0;
	volatile float p_low;
	volatile float fl_h;
	volatile s16 h;
	u8 i;

	// Typecast arguments
	volatile float fl_p_meas = (float)p_meas/100;	// Convert from Pa to hPa
	volatile float fl_t_meas = (float)t_meas/10;		// Convert from 10癒 to 1癒
	
	for (i=0; i<=16; i++)
	{
		if (p[i] < fl_p_meas) break;
		p_low = p[i];
	}
		
	if (i==0) 
	{
		hnoll = (float)(fl_p_meas - p[0])/(p[1] - p[0])*((float)(h0[1] - h0[0]));
	}
	else if (i<15) 
	{
		hnoll = (float)(fl_p_meas - p_low)*(1 - (fl_p_meas - p[i])* coef2)/(p[i] - p_low)*((float)(h0[i] - h0[i-1])) + h0[i-1];
	}
	else if (i==15)
	{
		hnoll = (float)(fl_p_meas - p_low)/(p[i] - p_low)*((float)(h0[i] - h0[i-1])) + h0[i-1];
	}
	else // i==16
	{
		hnoll = (float)(fl_p_meas - p[16])/(p[16] - p[15])*((float)(h0[16] - h0[15])) + h0[16];
	}
	
	// Compensate temperature error
	t0 = fl_t_meas/(1 - hnoll*Invt00*0.0065);
	fl_h = Invt00*t0*hnoll;
	h = (u16)fl_h;
	
	return (h);
}


vti_ps.h
// *************************************************************************************************
//
//	Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ 
//	 
//	 
//	  Redistribution and use in source and binary forms, with or without 
//	  modification, are permitted provided that the following conditions 
//	  are met:
//	
//	    Redistributions of source code must retain the above copyright 
//	    notice, this list of conditions and the following disclaimer.
//	 
//	    Redistributions in binary form must reproduce the above copyright
//	    notice, this list of conditions and the following disclaimer in the 
//	    documentation and/or other materials provided with the   
//	    distribution.
//	 
//	    Neither the name of Texas Instruments Incorporated nor the names of
//	    its contributors may be used to endorse or promote products derived
//	    from this software without specific prior written permission.
//	
//	  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
//	  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
//	  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
//	  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
//	  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
//	  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
//	  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//	  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//	  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
//	  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
//	  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// *************************************************************************************************

#ifndef VTI_PS_H_
#define VTI_PS_H_

// *************************************************************************************************
// Include section


// *************************************************************************************************
// Prototypes section
extern void ps_init(void);
extern void ps_start(void);
extern void ps_stop(void);
extern u32 ps_get_pa(void);
extern u16 ps_get_temp(void);
extern void init_pressure_table(void);
extern void update_pressure_table(s16 href, u32 p_meas, u16 t_meas);
extern s16 conv_pa_to_meter(u32 p_meas, u16 t_meas);


// *************************************************************************************************
// Defines section

// Port and pin resource for TWI interface to pressure sensor
// SCL=PJ.3, SDA=PJ.2, DRDY=P2.6
#define PS_TWI_IN            (PJIN)
#define PS_TWI_OUT           (PJOUT)
#define PS_TWI_DIR           (PJDIR)
#define PS_TWI_REN           (PJREN)
#define PS_SCL_PIN           (BIT3)
#define PS_SDA_PIN           (BIT2)

// Port, pin and interrupt resource for interrupt from acceleration sensor, DRDY=P2.6
#define PS_INT_IN            (P2IN)
#define PS_INT_OUT           (P2OUT)
#define PS_INT_DIR           (P2DIR)
#define PS_INT_IE            (P2IE)
#define PS_INT_IES           (P2IES)
#define PS_INT_IFG           (P2IFG)
#define PS_INT_PIN           (BIT6)

// TWI defines
#define PS_TWI_WRITE		(0u)
#define PS_TWI_READ			(1u)

#define PS_TWI_SEND_START	(0u)
#define	PS_TWI_SEND_RESTART	(1u)
#define	PS_TWI_SEND_STOP	(2u)
#define	PS_TWI_CHECK_ACK	(3u)

#define PS_TWI_8BIT_ACCESS	(0u)
#define PS_TWI_16BIT_ACCESS	(1u)

#define PS_TWI_SCL_HI		{ PS_TWI_OUT |=  PS_SCL_PIN; }
#define PS_TWI_SCL_LO		{ PS_TWI_OUT &= ~PS_SCL_PIN; }
#define PS_TWI_SDA_HI		{ PS_TWI_OUT |=  PS_SDA_PIN; }
#define PS_TWI_SDA_LO		{ PS_TWI_OUT &= ~PS_SDA_PIN; }
#define PS_TWI_SDA_IN		{ PS_TWI_OUT |=  PS_SDA_PIN; PS_TWI_DIR &= ~PS_SDA_PIN; }
#define PS_TWI_SDA_OUT		{ PS_TWI_DIR |=  PS_SDA_PIN; }


// *************************************************************************************************
// Global Variable section


// *************************************************************************************************
// Extern section


#endif /*VTI_PS_H_*/

你可能感兴趣的:(EZ430 Chronos 自带程序源码:高度计(气压计)示范程序)