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

📄 main.c

📁 SPI Control Module ready Code
💻 C
字号:
/*---------------------------------------------------------------*/
/* GPS data logger R0.02 (C)ChaN, 2008                           */
/*---------------------------------------------------------------*/

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <string.h>
#include "tff.h"
#include "diskio.h"


#define SYSCLK 10000000UL

#define	BEEP_ON()	TCCR0B=0b011
#define	BEEP_OFF()	TCCR0B=0b000
#define GPS_ON()	PORTB|=0x02
#define GPS_OFF()	PORTB&=0xFD
#define DELAY(dly)	for(Timer=dly;Timer;)

#define VTH_LOW		(WORD)(8000UL*100/3838)
#define VTH_HIGH	(WORD)(11500UL*100/3838)



FATFS fatfs;				/* File system object for each logical drive */
FIL file1;					/* File object */
BYTE Buff[82];				/* File/Console buffer */

volatile BYTE Timer;		/* 100Hz decrement timer */
volatile BYTE Stat;			/* Status */


typedef struct _fifo {
	uint8_t	idx_w;
	uint8_t	idx_r;
	uint8_t	count;
	uint8_t buff[150];
} FIFO;
volatile FIFO rxfifo;



/*---------------------------------------------------------*/
/* ADC interrupt                                           */
/*---------------------------------------------------------*/

ISR(ADC_vect)
{
	WORD n;
	static BYTE l, h;


	n = ADC;
	if (n < VTH_LOW) {
		if (l >= 15) {
			Stat |= 0x01;
		} else {
			l++;
		}
	} else {
		l = 0;
	}
	if (n > VTH_HIGH) {
		if (h >= 15) {
			Stat &= 0xFE;
		} else {
			h++;
		}
	} else {
		h = 0;
	}
	ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADIF)|_BV(ADIE)|0b111;
}


/*---------------------------------------------------------*/
/* 100Hz timer interrupt generated by OC1A                 */
/*---------------------------------------------------------*/


ISR(TIMER1_COMPA_vect)
{
	BYTE n;
	static WORD ivt_sync;


	n = Timer;
	if (n) Timer = n - 1;

	if (++ivt_sync >= 180 * 100) {
		ivt_sync = 0;
		Stat |= 4;
	}

	disk_timerproc();	/* Drive timer procedure of low level disk I/O module */

}



/*---------------------------------------------------------*/
/* User Provided Timer Function for FatFs module           */
/*---------------------------------------------------------*/
/* This is a real time clock service to be called from     */
/* FatFs module. Any valid time must be returned even if   */
/* the system does not support a real time clock.          */


DWORD get_fattime ()
{
	return	  ((2007UL - 1980) << 25)	/* Fixed to 2007.5.1, 00:00:00 */
			| ((5UL) << 21)
			| ((1UL) << 16)
			| (0 << 11)
			| (0 << 5)
			| (0 >> 1);
}


/*--------------------------------------------------------------------------*/
/* UART control */


static
void uart_init (void)
{
	cli();
	UCSR0B = 0;
	rxfifo.idx_r = 0;
	rxfifo.idx_w = 0;
	rxfifo.count = 0;
	UBRR0L = SYSCLK/16/4800;	// Enable USRAT0 in N81,4800bps
	UCSR0B = _BV(RXCIE0)|_BV(RXEN0)|_BV(TXEN0);
	Stat &= 0xFD;	// Clear overflow flag
	sei();
}


static
void uart_stop (void)
{
	UCSR0B = 0;
}


/* Get a received character */
static
uint8_t uart_get ()
{
	uint8_t d, i;


	i = rxfifo.idx_r;
	if (rxfifo.count == 0) return 0;
	d = rxfifo.buff[i++];
	cli();
	rxfifo.count--;
	sei();
	if(i >= sizeof(rxfifo.buff))
		i = 0;
	rxfifo.idx_r = i;

	return d;
}


/* Put a character to transmit */
static
void uart_put (uint8_t d)
{
	while (bit_is_clear(UCSR0A, UDRE0));
	UDR0 = d;
}


/* USART0 RXC interrupt */
ISR(USART_RX_vect)
{
	uint8_t d, n, i;


	d = UDR0;
	n = rxfifo.count;
	if(n < sizeof(rxfifo.buff)) {
		rxfifo.count = ++n;
		i = rxfifo.idx_w;
		rxfifo.buff[i++] = d;
		if(i >= sizeof(rxfifo.buff))
			i = 0;
		rxfifo.idx_w = i;
	} else {
		Stat |= 2;
	}
}



/*----------------------------------------------------*/
/*  Get a line received from GPS module               */
/*----------------------------------------------------*/

static
BYTE get_line (void)	// 0: Power fail occured, >0: Number of bytes received.
{
	BYTE c, i = 0;


	for (;;) {
		if (Stat & 1) return 0;	// When power fail is detected, return with zero.
		c = uart_get();
		if (Stat & 2) {			// When buffer overflow has occured, restert to receive line.
			uart_init();
			i = 0; c = 0;
		}
		if (!c || (i == 0 && c != '$')) continue;
		Buff[i++] = c;
		if (c == '\n') break;
		if (i >= sizeof(Buff)) i = 0;
	}
	return i;
}



/*--------------------------------------------------------------------------*/
/* Controls                                                                 */

static
void beep (BYTE len, BYTE cnt)
{
	while (cnt--) {
		BEEP_ON();
		DELAY(len);
		BEEP_OFF();
		DELAY(len);
	}
}




/* Compare sentence header string */
static
BYTE gp_comp (BYTE *str1, const prog_uint8_t *str2)
{
	BYTE c;

	do {
		c = pgm_read_byte(str2++);
	} while (c && c == *str1++);
	return c;
}



/* Initialize GPS module (depends on each product) */
static
void gp_init (void)
{
	const prog_char *s =
		PSTR("$PSRF106,21*0F\r\n");	// Select datum of WGS84 (for EM-406A)
	char c;

	while ((c = pgm_read_byte(s++)) != 0) uart_put(c);
}



/* Get a column item */
static
BYTE* gp_col (			/* Returns pointer to the item (returns a NULL when not found) */
	const BYTE* buf,	/* Pointer to the sentence */
	BYTE col			/* Column number (0 is the 1st item) */
) {
	BYTE c;


	while (col) {
		do {
			c = *buf++;
			if (c <= ' ') return NULL;
		} while (c != ',');
		col--;
	}
	return (BYTE*)buf;
}



static
void ioinit (void)
{
	PORTB = 0b00001101;	 	// Port B
	DDRB  = 0b00101110;
	PORTC = 0b00111111;		// Port C
	DDRC  = 0b00000000;
	PORTD = 0b10101110;		// Port D
	DDRD  = 0b01010010;

	SPCR = 0b01010000;			/* Initialize SPI port (Mode 0) */
	SPSR = 0b00000001;

	OCR1A = SYSCLK/8/100-1;		// Timer1: 100Hz interval (OC1A)
	TCCR1B = 0b00001010;
	TIMSK1 = _BV(OCIE1A);		// Enable TC1.oca interrupt

	OCR0A = SYSCLK/64/4000/2-1;	// Timer0: 4kHz sound (OC0A)
	TCCR0A = 0b01000010;

	ADMUX = 0b01000000 | 7;		// Select ADC input
	ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADIF)|_BV(ADIE)|0b111;

	sei();
}



/*-----------------------------------------------------------------------*/
/* Main                                                                  */


int main ()
{
	BYTE b, err, *p = NULL;
	WORD s;


	ioinit();
	f_mount(0, &fatfs);					/* Enable file I/O layer */

	for (;;) {
		uart_stop();
		GPS_OFF();
		Timer = 100;
		do {
			if (Stat & 1) Timer = 100;
		} while (Timer);

		GPS_ON();
		Timer = 255;
		do {
			if ((Stat & 1) || (disk_status(0) & STA_NODISK))  Timer = 255;
		} while (Timer);

		beep(5, 1);		// Single beep. Start to get current time.
		uart_init();
		gp_init();		// Initialize GPS module to let output data in NMEA-0183 format.
		do {			// Wait for valid RMC sentence.
			b = get_line();
			if (!b) break;
			if (gp_comp(Buff, PSTR("$GPRMC"))) continue;
			p = gp_col(Buff,2);
		} while (!p || *p != 'A');
		if (!b) continue;
		p = gp_col(Buff,9);		// Open log file with the name of current date (YYMMDD.log in UTC).
		if (!p) {
			 err = 3; break;
		}
		memcpy(&Buff[0], p+4, 2);
		memcpy(&Buff[2], p+2, 2);
		memcpy(&Buff[4], p+0, 2);
		strcpy_P(&Buff[6], PSTR(".log"));
		if (f_open(&file1, Buff, FA_OPEN_ALWAYS | FA_WRITE)
		 || f_lseek(&file1, file1.fsize)) {
			 err = 4; break;
		}

		beep(5, 2);		// Two beeps. Start logging.
		err = 0;
		while ((b = get_line()) > 0) {
			if (   !gp_comp(Buff, PSTR("$GPGGA"))	// Which sentence is logged?
				|| !gp_comp(Buff, PSTR("$GPRMC"))
			//	|| !gp_comp(Buff, PSTR("$GPGSA"))
			//	|| !gp_comp(Buff, PSTR("$GPGLL"))
			//	|| !gp_comp(Buff, PSTR("$GPGSV"))
			//	|| !gp_comp(Buff, PSTR("$GPZDA"))
			//	|| !gp_comp(Buff, PSTR("$GPVTG"))
			) {
				if (f_write(&file1, Buff, b, &s) || b != s) { err = 5; break; };
			}
			if ((Stat & 4) == 0) continue;
			if (f_sync(&file1)) { err = 6; break; };// Synchronize the file in interval of 300 sec.
			cli(); Stat &= 0xFB; sei();				// Clear sync request
		}
		if (err) break;

		// Turn-off GPS power and close the log file by power supply is discharged.
		uart_stop();
		GPS_OFF();
		if (f_close(&file1)) { err = 7; break; };

		// When a long beep is sounded, the shutdoun process has been succeeded.
		beep(50, 1);
	}

	// Unrecoverble error. Enter shutdown state.
	uart_stop();
	GPS_OFF();
	beep(25, err);
	for (;;);
}


⌨️ 快捷键说明

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