⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hardwareio.c

📁 LV24000的单片机DEMO程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************************
*
*   Copyright(c) 2004 ItoM BV
*   All Rights Reserved.
*
*   LV2400x evaluation kit: Take care of shadowing LV2400x registers
*   File name:	HardwareIo.c
*	Hardware platform for 3-wire chip
*	These functions are low level IO and system specific.
*
*************************************************************************/

#include <stdio.h>
#include "common.h"
#include "Lv24Ekit.h"

#ifdef USE_PRESET
#include "LcFls.h"
_rom BYTE gFlsRom[128]	_at(0x00f700);	// user' setting area in LC87F1564 flash
#endif //USE_PRESET

/* ************************************************************************************************
 *
 *  Function:   Init3wHardwareIo
 *
 *  Authors:    Hung van Le
 *  Purpose:    Configure the hardware GPIO for for 3-wire usage.
 *  Input:	Nothing
 *  Output:     Nothing
 *  Comments:   - The GPIO is configured as follows:
 *			NR_W is output of the uC, level is low (put 3W-device in read mode)
 *			CLOCK is output of the uC, level is high
 *			DATA is input of the uC
 *		- Interrupt is assigned to DATA-pin as system 3W-interrupt
 *		- Disable system 3W-interrupt		
 *
 * ************************************************************************************************
 * Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
 * ************************************************************************************************ */
void Init3wHardwareIo(void)
{
	// Config the GPIO
   	I3W_DIRPORT = (BYTE)(I3W_CLK_PIN_BM|
   		        //I3W_DATA_PIN_BM|
   		        I3W_NRW_PIN_BM|
   		        I3W2_CLK_PIN_BM|
   		        //I3W2_DATA_PIN_BM|
   		        I3W2_NRW_PIN_BM);   	// All 3-wires pins are output except data pins, RDS pins are input

	// Driving the GPIO to default level
   	I3W_PORT = I3W2_CLK_PIN_BM;  		// Clock is high, other pins are low (Read 3-wire mode)

	// Assign system interrupt to GPIO
   	_I45SL = 0x80;			// INT5(1Bh) at P26 (3-wire 1 DATA-pin), INT4(13h) at P20 (ext. RDS clock pin)
   	//_I45SL = 0x88;		// INT5(1Bh) at P26 (3-wire 1 DATA-pin), INT4(13h) at P22 (3-wire 2 DATA-pin)

	// Default is disabling 3W-interrupt
   	_I45CR = 0x00;			// Disable INT4/INT5
} // End Init3wHardwareIo

/* ************************************************************************************************
 *
 *  Function:   IoWrite3W
 *
 *  Authors:    Hung van Le
 *  Purpose:    Write 16 bit data to 3W-device
 *  Input:	byLow: low byte of the data
 *		byHigh: high byte of the data
 *  Output:     Nothing
 *  Global:	None.
 *  Comments:   - The LSB of the low byte will be written first
 *		- This function uses DGT4-protocol (CLOCK is default high)
 *
 * ************************************************************************************************
 * Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
 * ************************************************************************************************ */
void IoWrite3W(BYTE byLow, BYTE byHigh)
{
	// Prepare the 3-wire bus for writing
	_putbit(1, I3W_PORT, I3W_NRW_PIN); 		// nRW line high for writing
	_putbit(1, I3W_DIRPORT, I3W_DATA_PIN); 		// Program DATA PIN to output

	// Perfrom the 3W-write
	IoWriteByte3W(byLow);	// Write low byte
	IoWriteByte3W(byHigh);	// Write high byte

 	// Let the device latch data
	_putbit(0, I3W_DIRPORT, I3W_DATA_PIN); 	// Change DATA PIN to input mode
	_putbit(0, I3W_PORT, I3W_NRW_PIN); 	// nRW line low for latching data
} // End IoWrite3W

/* ************************************************************************************************
 *
 *  Function:   IoRead3W
 *
 *  Authors:    Hung van Le
 *  Purpose:    Read 8 bit data from 3W-device
 *  Input:	byReg: 8 bit data to be sent before the read (usually the register address for the read)
 *  Output:     The read data byte
 *  Comments:   - The LSB will be read first
 *		- This function uses DGT4-protocol (CLOCK is default high)
 *
 * ************************************************************************************************
 * Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
 * ************************************************************************************************ */
BYTE IoRead3W(BYTE byReg)
{
	BYTE byBitCnt;
	BYTE byData;

  	_putbit(1, I3W_PORT, I3W_NRW_PIN); 	// nRW line high for writing
	_putbit(1, I3W_DIRPORT, I3W_DATA_PIN); 	// Program DATA PIN to output

	// Write the register offset
	IoWriteByte3W(byReg);

	//_putbit(0, I3W_PORT, I3W_CLK_PIN);	// Clock low by exit for V3, leave it high for V4
	_putbit(0, I3W_DIRPORT, I3W_DATA_PIN); 	// Change DATA PIN to input mode
	_putbit(0, I3W_PORT, I3W_NRW_PIN); 	// nRW line low for latching data

	// Read the 8 bits data (LSB is read first)
    	byData = 0;
	for (byBitCnt=0; byBitCnt<8; byBitCnt++)
	{
		_putbit(0, I3W_PORT, I3W_CLK_PIN);	// Clock low -> The chip shifts its data out
		byData>>=1;				// Make room for next bit (the first shift is dummy!)
		if ( _getbit(I3W_PORT, I3W_DATA_PIN ) )
			byData |= 0x80;
		_putbit(1, I3W_PORT, I3W_CLK_PIN);	// Clock high
	}

	// Return the read data
	return(byData);
} // End IoRead3W

/* ************************************************************************************************
 *
 *  Function:   IoWriteByte3W
 *
 *  Authors:    Hung van Le
 *  Purpose:    Generate clock to send 8 bit data to 3W-device
 *  Input:	byData: 8 bit data to be sent
 *  Output:     Nothing
 *  Comments:   - This function is meant for internal usage (to be called by IoWrite3W or IoRead3W)
 *
 * ************************************************************************************************
 * Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
 * ************************************************************************************************ */
void IoWriteByte3W(BYTE byData)
{
	// Write 1 byte to the 3-wire device (LSB is written first)
	// Caller must prepare the bus for write mode before invoke this function
	BYTE byBitCnt;

	// Number of data bit
        byBitCnt = 8;

	// Write the data to the chip: LSB first
	while (byBitCnt)
	{
		_putbit(0, I3W_PORT, I3W_CLK_PIN);	// Clock low
		if (byData & 1)
		    _putbit(1, I3W_PORT, I3W_DATA_PIN);	// Drive data pin high
		else 
		    _putbit(0, I3W_PORT, I3W_DATA_PIN);	// Drive data pin low
		_putbit(1, I3W_PORT, I3W_CLK_PIN);	// Clock high
		byData >>=1;				// Next bit
		byBitCnt--;
	}
} // End IoWriteByte3W

/* ************************************************************************************************
 *
 *  Function:   Pulse3wNRW
 *
 *  Authors:    Hung van Le
 *  Purpose:    Pulse the 3W-NRW signal for specified time. Return the real time in us
 *  Input:	wStart: the pattern to send to the 3W-bus to start the pulse period
 *		wStop: the stop pattern to send to the 3W-bus after the period is expired
 *		dwTimeUs: time in us to pulse the NRW-signal
 *  Output:     The actual pulse time in us
 *  Global:	g_bySwFlag1 (W): clear/set SF1_PULSE3W_BUSY flag to mark pulse period
 *  Comments:   - This function is meant for measuring frequency of the 3W chip: the start pattern will start the counter 1
 *		  in the 3W-chip. When the pulse period expires, the NRW goes high which stops the counter 1 of the 3W-chip.
 *		  The stop pattern disables this counter (freezing the counter value). With the counter1 value and the pulse 
 *		  period, the frequency can be calculated
 *		- This function is not required when the external clock is used by frequency measurement
 *
 * ************************************************************************************************
 * Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
 * ************************************************************************************************ */
DWORD Pulse3wNRW(WORD wStart, WORD wStop, DWORD dwTimeUs)
{
	BYTE byTmp;
	WORD wInitialCnt, wExtraCnt;

	// Prepare timer 0 for measuring	
	wInitialCnt = ArmTimer0ForMsr(dwTimeUs);
	
	// No interrupt between starting the 2 counters
	byTmp = _IE;	// Save the org. interrupt state
	_IE = 0x00;

	// Start measuring.
#ifdef USE_USB
	// We use UsbWrite (support both DGT3/DGT4) to support both USB-mode and stand alone mode
	UsbWrite3wV3V4(LSB(wStart), MSB(wStart));	// Write the start pattern
#else  // USE_USB
	// For stand alone mode, using IoWrite3W (only support DGT4)
	IoWrite3W(LSB(wStart), MSB(wStart));
#endif //USE_USB

	// Start timer 0 of LC8715xx (in mode 2)
	_T0CNT = 0xE4;	// Set T0HRUN, T0LRUN, T0LONG, T0HIE bits (enable match TOHR interrupt)

	// Enable interrupt
	_IE = 0x80;

	// Wait until the timer expires - TODO: add time-out check
	while (g_bySwFlag1 & SF1_PULSE3W_BUSY);

	// No interrupt between stopping the 2 counters
	_IE = 0x00;

	// Timer expired. Let LV2400x enter write mode to stop its counter
    	_putbit(1, I3W_PORT, I3W_NRW_PIN);	// Drive NR_W high (Write mode)

	// We can not read the T0L/T0H because the LC8715xx clears these register when it stops.
	// So select extern input to freeze T0L/T0H for reading it. Be sure that nothing is 
	// toggling the time 0 extern input !!!
    	//_putbit(1, _T0CNT, _T0LEXT);	// Select extern input for timer 0
	_putbit(1, _T0CNT, 4);	// Select extern input for timer 0 (stop the timer)

	// Change DATA-pin to output: place here to avoid software overhead between stopping
	// LV2400x counter and stopping LC8715xx timer
    	_putbit(1, I3W_DIRPORT, I3W_DATA_PIN);

	// Restore system interrupt
	_IE = byTmp;

	// Fetch the extra count
	wExtraCnt = _T0H;	// Fetch high byte of timer 0 
	wExtraCnt <<= 8;
	wExtraCnt |= _T0L;	// Fetch low byte of timer 0 
	
	// Disable timer 0 - clear interrupt
    	_T0CNT = 0x00;	
		
	// Write the stop pattern
#ifdef USE_USB
	// We use UsbWrite (support both DGT3/DGT4) to support both USB-mode and stand alone mode
	UsbWrite3wV3V4(LSB(wStop), MSB(wStop));	// Write the start pattern
#else  // USE_USB
	// For stand alone mode, using IoWrite3W (only support DGT4)
	IoWrite3W(LSB(wStop), MSB(wStop));
#endif //USE_USB

	// Determine the real measuring time (in us)
	dwTimeUs = wInitialCnt + wExtraCnt;
	byTmp = _T0PRR; 		// Fetch prescaler
	byTmp += 1; 			// Number of Tcyc is prescaler+1
	dwTimeUs *= byTmp;		// dwTimeUs = number of Tcyc expired
	dwTimeUs += 12;			// Compensate the push/pop/ret of WriteReg between the last WriteReg and enable timer 0 (12 cycle)
	dwTimeUs *= LC8715XX_TCYC_NS; 	// dwTimeUs = time in ns
	dwTimeUs /= 1000;		// convert ns to us
	return(dwTimeUs);
} // End Pulse3wNRW

/* ************************************************************************************************
 *
 *  Function:   ArmTimer0ForMsr
 *
 *  Authors:    Hung van Le
 *  Purpose:    Calculate value of _T0PRR, _T0LR and _T0HR to work with timer 0 of LC87F1564
 *  Input:	dwTimeUs: time required for the timer in us
 *  Output:     The prescaler is written to _T0PRR
 *		The expected count value is written to _T0LR and _T0HR
 *		Return the expected count
 *  Global: 	g_bySwFlag1 (W): set SF1_PULSE3W_BUSY flag
 *  Comments:   - This function can be inline of function Pulse3wNRW.
 *
 * ************************************************************************************************
 * Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
 * ************************************************************************************************ */
WORD ArmTimer0ForMsr(DWORD dwTimeUs)
{
	DWORD dwTmp, dwCnt;
	BYTE  byPrr;

	switch (dwTimeUs)
	{
#ifdef CF8MHZ
	// First do look up for familiar values (t = byPrr*375ns*Cnt)
	// PRR	Clock	Count	Time(ms)
	// 2	750ns	10666	8ms	
	// 2	750ns	42666	32ms
	// 3	1125ns	56888	64ms
	// 5	1875ns	53333	100ms
	// Reduce time due to software overhead
	// 2	750ns	8000	6ms	
	// 2	750ns	40000	30ms
	// 4	1500ns	40000	60ms
	// 5	1875ns	51200	96ms
	case LV_MSR_TIME_8ms:
		byPrr = 2;
		dwCnt = 8000;	// should be 10666
		break;
 	case LV_MSR_TIME_32ms:
		byPrr = 2;
		dwCnt = 40000;	// should be 42666
		break;
	case LV_MSR_TIME_64ms:
		byPrr = 4;	// should be 3
		dwCnt = 40000;	// was 56888
		break;
	case LV_MSR_TIME_100ms:
		byPrr = 5;
		dwCnt = 51200;	// should be 53333
		break;
#endif //CF8MHZ
#ifdef CF12MHZ
	// First do look up for familiar values (t = byPrr*375ns*Cnt)
	// PRR	Clock	Count	Time(ms)
	// 2	500ns	16000	8ms	
	// 2	500ns	64000	32ms
	// 4	1000ns	64000	64ms
	// 7	1750ns	57142	100ms
	// Reduce time due to software overhead
	// 2	500ns	12000	6ms	
	// 2	500ns	60000	30ms
	// 4	1000ns	60000	60ms
	// 7	1750ns	54857	96ms
	case LV_MSR_TIME_8ms:
		byPrr = 2;
		dwCnt = 12000;	// should be 16000
		break;
 	case LV_MSR_TIME_32ms:
		byPrr = 2;
		dwCnt = 60000;	// should be 64000
		break;
	case LV_MSR_TIME_64ms:
		byPrr = 4;    
		dwCnt = 60000;	// should be 64000
		break;
	case LV_MSR_TIME_100ms:
		byPrr = 5;
		dwCnt = 54857;	// should 57142
		break;
#endif //CF12MHZ

	// Remaining values: Calulate the setting for time 0
	default:
		// Find out the approriate value for T0PRR, T0LR, T0HR
		dwTimeUs *= 1000; // Convert us to ns
		for (byPrr=2; byPrr<20; byPrr++)
		{
			dwTmp = byPrr;
			dwTmp *= LC8715XX_TCYC_NS; 	// Cycle time in ns
			dwCnt = dwTimeUs/dwTmp;		// Count value
			if (dwCnt < 0xFFFF)
				break;			// Break for-loop: Find approriate value
		}
		break;	// break case 
	} // EndSwitch

	// Prepare timer 0 of LC8715xx
	_T0CNT = 0x10;				// Set T0LONG bit for 16 bit timer, stop counter, clear interrupt
	_T0PRR = (byPrr-1);			// Prescaler match register (T0PRR)
	_T0LR = LSB(dwCnt);			// data match register T0LR (count low)
	_T0HR = MSB(dwCnt);			// data match register T0HR (count high)
	g_bySwFlag1 |= SF1_PULSE3W_BUSY;	// Mark measuring in progress
	return((WORD)dwCnt);
} // End ArmTimer0ForMsr

/* ************************************************************************************************
 *
 *  Function:   HandleTimer0Done
 *
 *  Authors:    Hung van Le
 *  Purpose:    Invoked by timer 0 interrupt when the timer period expired
 *  Input:	Nothing
 *  Output:     Nothing
 *  Global: 	g_bySwFlag1 (W): Clear SF1_PULSE3W_BUSY flag
 *  Comments:   This function is part of timer 0 interrupt handler
 *
 * ************************************************************************************************
 * Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
 * ************************************************************************************************ */
void HandleTimer0Done(void)
{
	// Mark timer 0 expired (clear counter busy flag)
	g_bySwFlag1 &= (BYTE)(~SF1_PULSE3W_BUSY);
} // End HandleTimer0Done

/* ************************************************************************************************
 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -