interrupt [TIM2_OVF] void timer2_ovf_isr(void) { char i; if (++GlobalS==60) { if (++GlobalM==60) { GlobalH++; GlobalM=0; } GlobalS=0; } LED=!LED; }
I think everything is clear and simple. delay_ms(100); printf("@00000001\r\n"); GlobalH=0; GlobalM=0; GlobalS=0; GlobalMs=0;
Trans=1; MS=GlobalMs_Timer/2.56; H=GlobalH; M=GlobalM; S=GlobalS; printf("@%02u%02u%02u%02u%02u\r\n",Trans,H,M,S,MS);
For example: @ 0102030405 means that the transponder with the number 01 passed a loop for 2 hours 3 minutes 4 seconds and 50ms /***************************************************** This program was produced by the CodeWizardAVR V2.05.0 Professional Automatic Program Generator © Copyright 1998-2010 Pavel Haiduc, HP InfoTech srl http://www.hpinfotech.com Project : Version : Date : 01.04.2013 Author : Company : Comments: Chip type : ATmega16 Program type : Application AVR Core Clock frequency: 7,372800 MHz Memory model : Small External RAM size : 0 Data Stack size : 256 *****************************************************/ #include <mega16.h> #ifndef RXB8 #define RXB8 1 #endif #ifndef TXB8 #define TXB8 0 #endif #ifndef UPE #define UPE 2 #endif #ifndef DOR #define DOR 3 #endif #ifndef FE #define FE 4 #endif #ifndef UDRE #define UDRE 5 #endif #ifndef RXC #define RXC 7 #endif #define FRAMING_ERROR (1<<FE) #define PARITY_ERROR (1<<UPE) #define DATA_OVERRUN (1<<DOR) #define DATA_REGISTER_EMPTY (1<<UDRE) #define RX_COMPLETE (1<<RXC) // USART Receiver buffer #define RX_BUFFER_SIZE 32 char rx_buffer[RX_BUFFER_SIZE]; #if RX_BUFFER_SIZE <= 256 unsigned char rx_wr_index,rx_rd_index,rx_counter; #else unsigned int rx_wr_index,rx_rd_index,rx_counter; #endif // This flag is set on USART Receiver buffer overflow bit rx_buffer_overflow; // USART Receiver interrupt service routine interrupt [USART_RXC] void usart_rx_isr(void) { char status,data; status=UCSRA; data=UDR; if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) { rx_buffer[rx_wr_index++]=data; #if RX_BUFFER_SIZE == 256 // special case for receiver buffer size=256 if (++rx_counter == 0) { #else if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0; if (++rx_counter == RX_BUFFER_SIZE) { rx_counter=0; #endif rx_buffer_overflow=1; } } } #ifndef _DEBUG_TERMINAL_IO_ // Get a character from the USART Receiver buffer #define _ALTERNATE_GETCHAR_ #pragma used+ char getchar(void) { char data; while (rx_counter==0); data=rx_buffer[rx_rd_index++]; #if RX_BUFFER_SIZE != 256 if (rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0; #endif #asm("cli") --rx_counter; #asm("sei") return data; } #pragma used- #endif // USART Transmitter buffer #define TX_BUFFER_SIZE 256 char tx_buffer[TX_BUFFER_SIZE]; #if TX_BUFFER_SIZE <= 256 unsigned char tx_wr_index,tx_rd_index,tx_counter; #else unsigned int tx_wr_index,tx_rd_index,tx_counter; #endif // USART Transmitter interrupt service routine interrupt [USART_TXC] void usart_tx_isr(void) { if (tx_counter) { --tx_counter; UDR=tx_buffer[tx_rd_index++]; } } #ifndef _DEBUG_TERMINAL_IO_ // Write a character to the USART Transmitter buffer #define _ALTERNATE_PUTCHAR_ #pragma used+ void putchar(char c) { if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0)) { tx_buffer[tx_wr_index++]=c; ++tx_counter; } else UDR=c; } #pragma used- #endif // Standard Input/Output functions #include <stdio.h> #include <delay.h> char GlobalH,GlobalM,GlobalS,GlobalMs; float TempFloat; #define GlobalMs_Timer TCNT2 #define LED PORTD.7 unsigned int Trans; // External Interrupt 0 service routine interrupt [EXT_INT0] void ext_int0_isr(void) { delay_ms(100); printf("@00000001\r\n"); GlobalH=0; GlobalM=0; GlobalS=0; GlobalMs=0; } interrupt [EXT_INT1] void ext_int1_isr(void) { char H,M,S,MS,Trans; Trans=1; MS=GlobalMs_Timer/2.56; H=GlobalH; M=GlobalM; S=GlobalS; printf("@%02u%02u%02u%02u%02u\r\n",Trans,H,M,S,MS); } interrupt [EXT_INT2] void ext_int2_isr(void) { } interrupt [TIM0_OVF] void timer0_ovf_isr(void) { } interrupt [TIM2_OVF] void timer2_ovf_isr(void) { char i; if (++GlobalS==60) { if (++GlobalM==60) { GlobalH++; GlobalM=0; } GlobalS=0; } LED=!LED; } void main(void) { PORTA=0x00; DDRA=0x00; PORTB=0x00; DDRB=0x00; PORTC=0x00; DDRC=0x00; PORTD=0b1001100; DDRD=0x80; TCCR0=0x05; TCNT0=0x00; OCR0=0x00; ASSR=0x08; TCCR2=0x05; TCNT2=0x00; OCR2=0x00; GICR|=0xE0; MCUCR=0x0A; MCUCSR=0x00; GIFR=0xE0; TIMSK=0x41; // USART initialization // Communication Parameters: 8 Data, 1 Stop, No Parity // USART Receiver: On // USART Transmitter: On // USART Mode: Asynchronous // USART Baud Rate: 9600 UCSRA=0x00; UCSRB=0xD8; UCSRC=0x86; UBRRH=0x00; UBRRL=0x2F; #asm("sei") while (1) { } }
interrupt [USART_RXC] void usart_rx_isr(void) { char status,data; status=UCSRA; data=UDR; if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) { rx_buffer[rx_wr_index++]=data; if (data==0x0A) {TimeToInit=1;} // #if RX_BUFFER_SIZE == 256 // special case for receiver buffer size=256 if (++rx_counter == 0) { #else if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0; if (++rx_counter == RX_BUFFER_SIZE) { rx_counter=0; #endif rx_buffer_overflow=1; } } }
But in the main loop we initialize: if (TimeToInit) { putchar(1); printf("$\t%i\t7\t0\t1\t1\t",decoderid); putchar(0xF8); putchar(0xF9); printf("\r\n"); GlobalS=0; GlobalMs_Timer=0; sequence_number=0; TimeToInit=0; }
I did not find a complete description of the protocol, I found only a partial one. An entry to the COM port will be sent as follows:01 24 09 31 30 30 09 37 09 30 09 31 09 31 09 F8 F9 0D 0AHere the decoder number is 100. The recording always starts with a byte (0x01). Next comes the $ sign. Between each value is a Tab (0x09) sign. All entries end with a carriage return (0x0D 0x0A). Well, do not forget that you need to reset the time and sequence_number. sequence_number is the number of the parcel, incremented with each parcel.
# 100 980 0 x06BAThe bytes are like this:
01 23 09 31 30 30 09 31 30 32 38 09 30 09 78 39 42 39 46 0D 0AHere you can see the decoder number, sequence_number, which is zero (I don’t know why) and the checksum. The checksum is considered in the putchar procedure:
void putchar(char c) { while (tx_counter == TX_BUFFER_SIZE); #asm("cli") crcwork = (crcTable[(crcwork >> 8) & 0xff] ^ (crcwork << 8) ^ c); // if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0)) { tx_buffer[tx_wr_index++]=c; ++tx_counter; } else UDR=c; #asm("sei") }
The crcTable table is calculated in advance; it is here: if (TimeToSendAmbStatus) { sequence_number++; putchar(1); crcwork=0xFFFF; printf("#\t%i\t%i\t0\t",decoderid,sequence_number); printf("x%02X%02X\r\n",((crcwork>>8)&0xff),(crcwork&0xff)); TimeToSendAmbStatus=0; }
Here you can see how the sequece_number is incremented. Initially, 0x01 is sent, then crcwork = 0xFFFF is reset. Helmet part of the parcel. At the same time, a checksum is considered. The next action helmet is our checksum and carriage return. And so every four seconds: interrupt [TIM2_OVF] void timer2_ovf_isr(void) { static char times; if (++times==4) { TimeToSendAmbStatus=1; times=0; } GlobalS++; LED=!LED; }
#define TranspondersCountMax 20 unsigned long int Transponders[TranspondersCountMax]; unsigned long int TranspondersTimeS[TranspondersCountMax]; unsigned int TranspondersTimeMS[TranspondersCountMax]; char TransponderNeedToSend, TranspondersCountInt, TranspondersCountMain;
The buffer is cyclical by the way. And this is how we will fill the buffer: interrupt [EXT_INT1] void ext_int1_isr(void) { unsigned long int S; unsigned int MS; MS=GlobalMs_Timer*3.90625; S=GlobalS; if (TransponderNeedToSend<TranspondersCountMax) { TransponderNeedToSend++; Transponders[TranspondersCountInt]=1234567; TranspondersTimeS[TranspondersCountInt]=S; TranspondersTimeMS[TranspondersCountInt]=MS; if (++TranspondersCountInt==TranspondersCountMax) TranspondersCountInt=0; } }
And in the main loop: if (TransponderNeedToSend) { sequence_number++; putchar(1); crcwork=0xFFFF; printf("@\t%i\t%i\t%07lu\t%u.%03u\t130\t119\t2\t", decoderid, sequence_number, Transponders[TranspondersCountMain], TranspondersTimeS[TranspondersCountMain], TranspondersTimeMS[TranspondersCountMain]); //putchar('@'); //putchar(9); //printf("%i",decoderid); //putchar(9); //printf("%i",sequence_number); //putchar(9); //printf("%07lu",Trans); //putchar(9); //printf("%u.%03u",S,MS); //putchar(9); //printf("130"); //putchar(9); //printf("119"); //putchar(9); //printf("2"); //putchar(9); printf("x%02X%02X\r\n",((crcwork>>8)&0xff),(crcwork&0xff)); if (++TranspondersCountMain==TranspondersCountMax) TranspondersCountMain=0; TransponderNeedToSend--; }
The comments indicate the same thing, only easier to understand, because the line "@ \ t% i \ t% i \ t% 07lu \ t% u.% 03u \ t130 \ t119 \ t2 \ t" will break the leg. Sending one, counting checksum is the same as sending decoder status.@ 100 10 1234567 37.589 130 119 2 xEB94As you can see, everything is very simple.
Source: https://habr.com/ru/post/196514/
All Articles