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

📄 tsc2000.c

📁 嵌入式试验箱S3C2410的bootloader源代码
💻 C
字号:
/* * Functions to access the TSC2000 controller on TRAB board (used for scanning * thermo sensors) * * Copyright (C) 2003 Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de * * Copyright (C) 2002 DENX Software Engineering, Wolfgang Denk, wd@denx.de * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <common.h>#include <s3c2400.h>#include "tsc2000.h"#include "Pt1000_temp_data.h"/* helper function */#define abs(value) (((value) < 0) ? ((value)*-1) : (value))/* * Maximal allowed deviation between two immediate meassurments of an analog * thermo channel. 1 DIGIT = 0.0276 癈. This is used to filter sporadic * "jumps" in measurment. */#define MAX_DEVIATION	18	/* unit: DIGITs of adc; 18 DIGIT = 0.5 癈 */void spi_init(void){	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();	S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();	int i;	/* Configure I/O ports. */	gpio->PDCON = (gpio->PDCON & 0xF3FFFF) | 0x040000;	gpio->PGCON = (gpio->PGCON & 0x0F3FFF) | 0x008000;	gpio->PGCON = (gpio->PGCON & 0x0CFFFF) | 0x020000;	gpio->PGCON = (gpio->PGCON & 0x03FFFF) | 0x080000;	CLR_CS_TOUCH();	spi->ch[0].SPPRE = 0x1F; /* Baud-rate ca. 514kHz */	spi->ch[0].SPPIN = 0x01; /* SPI-MOSI holds Level after last bit */	spi->ch[0].SPCON = 0x1A; /* Polling, Prescaler, Master, CPOL=0,				    CPHA=1 */	/* Dummy byte ensures clock to be low. */	for (i = 0; i < 10; i++) {		spi->ch[0].SPTDAT = 0xFF;	}	spi_wait_transmit_done();}void spi_wait_transmit_done(void){	S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();	while (!(spi->ch[0].SPSTA & 0x01)); /* wait until transfer is done */}void tsc2000_write(unsigned short reg, unsigned short data){	S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();	unsigned int command;	SET_CS_TOUCH();	command = reg;	spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;	spi_wait_transmit_done();	spi->ch[0].SPTDAT = (command & 0x00FF);	spi_wait_transmit_done();	spi->ch[0].SPTDAT = (data & 0xFF00) >> 8;	spi_wait_transmit_done();	spi->ch[0].SPTDAT = (data & 0x00FF);	spi_wait_transmit_done();	CLR_CS_TOUCH();}unsigned short tsc2000_read (unsigned short reg){	unsigned short command, data;	S3C24X0_SPI * const spi = S3C24X0_GetBase_SPI();	SET_CS_TOUCH();	command = 0x8000 | reg;	spi->ch[0].SPTDAT = (command & 0xFF00) >> 8;	spi_wait_transmit_done();	spi->ch[0].SPTDAT = (command & 0x00FF);	spi_wait_transmit_done();	spi->ch[0].SPTDAT = 0xFF;	spi_wait_transmit_done();	data = spi->ch[0].SPRDAT;	spi->ch[0].SPTDAT = 0xFF;	spi_wait_transmit_done();	CLR_CS_TOUCH();	return (spi->ch[0].SPRDAT & 0x0FF) | (data << 8);}void tsc2000_set_mux (unsigned int channel){	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();	CLR_MUX1_ENABLE; CLR_MUX2_ENABLE;	CLR_MUX3_ENABLE; CLR_MUX4_ENABLE;	switch (channel) {	case 0:		CLR_MUX0; CLR_MUX1;		SET_MUX1_ENABLE;		break;	case 1:		SET_MUX0; CLR_MUX1;		SET_MUX1_ENABLE;		break;	case 2:		CLR_MUX0; SET_MUX1;		SET_MUX1_ENABLE;		break;	case 3:		SET_MUX0; SET_MUX1;		SET_MUX1_ENABLE;		break;	case 4:		CLR_MUX0; CLR_MUX1;		SET_MUX2_ENABLE;		break;	case 5:		SET_MUX0; CLR_MUX1;		SET_MUX2_ENABLE;		break;	case 6:		CLR_MUX0; SET_MUX1;		SET_MUX2_ENABLE;		break;	case 7:		SET_MUX0; SET_MUX1;		SET_MUX2_ENABLE;		break;	case 8:		CLR_MUX0; CLR_MUX1;		SET_MUX3_ENABLE;		break;	case 9:		SET_MUX0; CLR_MUX1;		SET_MUX3_ENABLE;		break;	case 10:		CLR_MUX0; SET_MUX1;		SET_MUX3_ENABLE;		break;	case 11:		SET_MUX0; SET_MUX1;		SET_MUX3_ENABLE;		break;	case 12:		CLR_MUX0; CLR_MUX1;		SET_MUX4_ENABLE;		break;	case 13:		SET_MUX0; CLR_MUX1;		SET_MUX4_ENABLE;		break;	case 14:		CLR_MUX0; SET_MUX1;		SET_MUX4_ENABLE;		break;	case 15:		SET_MUX0; SET_MUX1;		SET_MUX4_ENABLE;		break;	default:		CLR_MUX0; CLR_MUX1;	}}void tsc2000_set_range (unsigned int range){	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();	switch (range) {	case 1:		CLR_SEL_TEMP_V_0; SET_SEL_TEMP_V_1;		CLR_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;		break;	case 2:		CLR_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;		CLR_SEL_TEMP_V_2; SET_SEL_TEMP_V_3;		break;	case 3:		SET_SEL_TEMP_V_0; CLR_SEL_TEMP_V_1;		SET_SEL_TEMP_V_2; CLR_SEL_TEMP_V_3;		break;	}}u16 tsc2000_read_channel (unsigned int channel){	u16 res;	tsc2000_set_mux(channel);	udelay(20 * TSC2000_DELAY_BASE);	tsc2000_write(TSC2000_REG_ADC, 0x2036);	adc_wait_conversion_done ();	res = tsc2000_read(TSC2000_REG_AUX1);	return res;}s32 tsc2000_contact_temp (void){	long adc_pt1000, offset;	long u_pt1000;	long contact_temp;	long temp1, temp2;	tsc2000_reg_init ();	tsc2000_set_range (3);	/*	 * Because of sporadic "jumps" in the measured adc values every	 * channel is read two times. If there is a significant difference	 * between the two measurements, then print an error and do a third	 * measurement, because it is very unlikely that a successive third	 * measurement goes also wrong.	 */	temp1 = tsc2000_read_channel (14);	temp2 = tsc2000_read_channel (14);	if (abs(temp2 - temp1) < MAX_DEVIATION)		adc_pt1000 = temp2;	else {		printf ("%s: read adc value (channel 14) exceeded max allowed "			"deviation: %d * 0.0276 癈\n",			__FUNCTION__, MAX_DEVIATION);		printf ("adc value 1: %ld DIGITs\nadc value 2: %ld DIGITs\n",			temp1, temp2);		adc_pt1000 = tsc2000_read_channel (14);		printf ("use (third read) adc value: adc_pt1000 = "			"%ld DIGITs\n",	adc_pt1000);	}	debug ("read channel 14 (pt1000 adc value): %ld\n", adc_pt1000);	temp1 = tsc2000_read_channel (15);	temp2 = tsc2000_read_channel (15);	if (abs(temp2 - temp1) < MAX_DEVIATION)		offset = temp2;	else {		printf ("%s: read adc value (channel 15) exceeded max allowed "			"deviation: %d * 0.0276 癈\n",			__FUNCTION__, MAX_DEVIATION);		printf ("adc value 1: %ld DIGITs\nadc value 2: %ld DIGITs\n",			temp1, temp2);		offset = tsc2000_read_channel (15);		printf ("use (third read) adc value: offset = %ld DIGITs\n",			offset);	}	debug ("read channel 15 (offset): %ld\n", offset);	/*	 * Formula for calculating voltage drop on PT1000 resistor: u_pt1000 =	 * x_range3 * (adc_raw - offset) / 10. Formula to calculate x_range3:	 * x_range3 = (2500 * (1000000 + err_vref + err_amp3)) / (4095*6). The	 * error correction Values err_vref and err_amp3 are assumed as 0 in	 * u-boot, because this could cause only a very small error (< 1%).	 */	u_pt1000 = (101750 * (adc_pt1000 - offset)) / 10;	debug ("u_pt1000: %ld\n", u_pt1000);	if (tsc2000_interpolate(u_pt1000, Pt1000_temp_table,				&contact_temp) == -1) {		printf ("%s: error interpolating PT1000 vlaue\n",			 __FUNCTION__);		return (-1000);	}	debug ("contact_temp: %ld\n", contact_temp);	return contact_temp;}void tsc2000_reg_init (void){	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();	tsc2000_write(TSC2000_REG_ADC, 0x2036);	tsc2000_write(TSC2000_REG_REF, 0x0011);	tsc2000_write(TSC2000_REG_DACCTL, 0x0000);	CON_MUX0;	CON_MUX1;	CON_MUX1_ENABLE;	CON_MUX2_ENABLE;	CON_MUX3_ENABLE;	CON_MUX4_ENABLE;	CON_SEL_TEMP_V_0;	CON_SEL_TEMP_V_1;	CON_SEL_TEMP_V_2;	CON_SEL_TEMP_V_3;	tsc2000_set_mux(0);	tsc2000_set_range(0);}int tsc2000_interpolate(long value, long data[][2], long *result){	int i;	/* the data is sorted and the first element is upper	 * limit so we can easily check for out-of-band values	 */	if (data[0][0] < value || data[1][0] > value)		return -1;	i = 1;	while (data[i][0] < value)		i++;	/* To prevent overflow we have to store the intermediate	   result in 'long long'.	*/	*result = data[i-1][1] +		((unsigned long long)(data[i][1] - data[i-1][1])		 * (unsigned long long)(value - data[i-1][0]))		/ (data[i][0] - data[i-1][0]);	return 0;}void adc_wait_conversion_done(void){	while (!(tsc2000_read(TSC2000_REG_ADC) & (1 << 14)));}

⌨️ 快捷键说明

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