Перейти к содержанию

Inmixxx Channel

Members
  • Постов

    11
  • Зарегистрирован

  • Посещение

Достижения Inmixxx Channel

Новичок

Новичок (1/14)

  • 10 постов на форуме
  • Неделя на форуме
  • Месяц на форуме
  • Год на форуме

Последние значки

0

Репутация

  1. Пока запустил, подает на порт нужные данные. Выводит 'Connect' раз 9 потом 'No ECU' Копаю дальше. Нужно сделать нормальный пункт меню, мне тоже не нравится это решение. Лёд тронулся. /******************************************************* This program was created by the CodeWizardAVR V3.12 Advanced Automatic Program Generator © Copyright 1998-2014 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.com Project : Lada ECU Monitor Version : 1.02 Date : 09.03.2017 Author : mr_smit , inmixxx Company : Comments: Chip type : ATmega32 Program type : Application AVR Core Clock frequency: 8,000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 512 *******************************************************/ #include <mega32.h> #include <alcd.h> // Alphanumeric LCD functions #include <delay.h> #include <string.h> #include <stdio.h> // Standard Input/Output functions #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) #define Connect 1 #define ReadData 2 #define ReadError 3 #define SpeedSample 4 int mode; #define HI(x) ((x)>>8) #define LO(x) ((x)& 0xFF) char convert[32]; #define BUFFER_SIZE 200 unsigned char buffer[BUFFER_SIZE]; // приемный буффер flash unsigned char startCommunication[] = {0x81,0x10,0xf1,0x81,0x03}; flash unsigned char readDataByLocalIdentifier_RLI_ASS[] = {0x82,0x10,0xF1,0x21,0x01,0xA5}; flash unsigned char readDTCByStatus[] = {0x84,0x10,0xF1,0x18,0x00,0x00,0x00,0x9D}; flash unsigned char clearDiagnosticInformation[] = {0x83,0x10,0xf1,0x14,0x00,0x00,0x98}; // для истории // flash unsigned char startDiagnosticSession[] = {0x83,0x10,0xF1,0x10,0x81,0x0A,0x1F}; // flash unsigned char stopCommunication[] = {0x81,0x10,0xf1,0x82,0x04}; // flash unsigned char stopDiagnosticSession[] = {0x81,0x10,0xf1,0x20,0xA2}; // flash unsigned char testerPresent[] = {0x82,0x10,0xf1,0x3E,0x01,0xC2}; // flash unsigned char readDataByLocalIdentifier_RLI_FT[] = {0x82,0x10,0xF1,0x21,0x03,0xA7}; volatile bit StartSend, first_draw, go, zamer_finish; volatile unsigned char counter; volatile unsigned int ms; volatile unsigned int dsec; unsigned char Connect_Delay; // 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) { buffer[counter] = data; if (++counter == BUFFER_SIZE) { counter = 0; } } } void SendCommand (flash unsigned char *command, unsigned char length) { counter = 0; while (length--) { while(!(UCSRA & (1<<UDRE))); // ждем окончания передачи байта UDR = *command++; } } // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { // Reinitialize Timer 0 value TCNT0=0x06; if (++ms > 250) { ms = 0; StartSend = 1; // разрешаем отправку запроса через каждые 250 мс } } // Timer1 overflow interrupt service routine interrupt [TIM1_OVF] void timer1_ovf_isr(void) { // Reinitialize Timer1 value TCNT1H=0xE796 >> 8; // таймер срабатывает каждые 0,1 сек TCNT1L=0xE796 & 0xff; if (++dsec > 300) { // даем на разгон 30 сек TCCR1B=0x00; go = 0; zamer_finish = 1; } } void main(void) { // Declare your local variables here // Input/Output Ports initialization DDRA=0b00000000; PORTA=0b01100000; DDRB=0b00000000; PORTB=0b00000000; DDRC=0b11111111; PORTC=0b00000000; DDRD=0b00000000; PORTD=0b00000000; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 250,000 kHz TCCR0=0x03; TCNT0=0x06; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 62,500 kHz // Mode: Normal top=0xFFFF // Input Capture on Falling Edge // Timer1 Overflow Interrupt: On TCNT1H=0xE7; TCNT1L=0x96; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0b00000101; // USART initialization // Communication Parameters: 8 Data, 1 Stop, No Parity // USART Receiver: On // USART Transmitter: On // USART Mode: Asynchronous // USART Baud Rate: 10400 UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM); UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8); UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL); UBRRH=0x00; UBRRL=0x2F; // Analog Comparator initialization // Analog Comparator: Off // The Analog Comparator's positive input is // connected to the AIN0 pin // The Analog Comparator's negative input is // connected to the AIN1 pin ACSR=0b10000000; SFIOR=0; StartSend =1; // Global enable interrupts #asm("sei") lcd_init(16); lcd_clear(); lcd_gotoxy(0,9); lcd_putsf("Run"); mode=1; while (1) { // // lcd_gotoxy(0,9); // lcd_putsf("Run"); if (PINA.6 == 0) { // если нажали кнопку выбора режима delay_ms(15); if (PINA.6 == 0) { lcd_gotoxy(0,9); lcd_putsf("mode++"); mode++; // меняем режим if(mode>4){ mode=2; } TCCR1B=0x00; dsec = 0; // сбрасываем замер времени go = 0; zamer_finish = 0; //first_draw = 1; // перерисовываем экран при первом заходе в режим } } if (PINA.5 == 0) { // если нажали кнопку сброса delay_ms(15); if (PINA.5 == 0) { if (mode == ReadError) { SendCommand(clearDiagnosticInformation,7); // стираем ошибки delay_ms(500); // даём ЭБУ время на стирание ошибок // first_draw = 1; lcd_gotoxy(0,9); lcd_putsf("Rd.Err"); // перерисовываем экран } else if (mode == SpeedSample) { lcd_gotoxy(0,9); lcd_putsf("spdsamp"); TCCR1B=0x00; dsec = 0; // сбрасываем замер времени go = 0; zamer_finish = 0; // first_draw = 1; // перерисовываем экран } } } switch (mode) { // смотрим какой режим case Connect: // если только что включились => подключаемся к ЭБУ if (StartSend == 1) { lcd_clear(); // очистка дисплея lcd_gotoxy(0,0); // 0 позиция, верхняя строка lcd_putsf("Conn"); delay_ms(100); SendCommand(startCommunication,5); StartSend = 0; if (++Connect_Delay > 8) { // делаем 8 попыток подключиться lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("NO ECU"); // если нет ответа, то выводим соответствующее сообщение delay_ms(2000); // и через секунду пробуем подключиться вновь Connect_Delay = 0; } } else { if (counter > 11) { // парсим запрос + ответ unsigned char i = 0; unsigned int crc = 0; for (i=5;i<11;i++) { // запрос + ответ = 12 байт crc = crc + buffer[i]; // считаем контрольную сумму } i = crc & 0xFF; // берем 2 младших разряда lcd_gotoxy(0,9); lcd_putsf("c>11 "); if ( buffer[11] == i ) { // проверяем контрольную сумму if ( buffer[8] == 0xC1 ) { // положительный ответ startCommunication lcd_gotoxy(0,0); lcd_putsf("StComm"); // если нет ответа, то выводим соответствующее сообщение delay_ms(2000); //SendCommand(startDiagnosticSession,7); // запрашиваем диагностику, ответ не проверяем (хотя надо бы...) mode = ReadData; // переходим в режим чтения данных // first_draw = 1; } } counter = 0; // сбрасываем counter иначе опять попадем под условие if (counter > 11) } } break; case ReadData: lcd_gotoxy(0,9); lcd_putsf("Rd.Dat"); if (StartSend == 1) { lcd_gotoxy(0,9); lcd_putsf("StartS"); SendCommand(readDataByLocalIdentifier_RLI_ASS,6); StartSend = 0; } else { if (counter>48) { // 6 байт запрос + 43 байта ответ (4-й байт в ответе - число байтов в посылке) unsigned char i = 0; unsigned int crc = 0; //unsigned char drossel = 0; for (i=6;i<48;i++) { crc = crc + buffer[i]; // считаем контрольную сумму } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[48] == i ) { // проверяем контрольную сумму i = buffer[20] - 0x28; // вычисляем температуру двигателя if (i & 0x80) { // если она ниже нуля i = 256 - i; sprintf(convert,"-%d°",i); if (strlen(convert) <= 3) { // стираем лишнее справа от параметра в случае если он стал одинарным или двойным lcd_gotoxy(0,1); lcd_puts(strcat(convert, " ")); // выводим надпись в указанных координатах } else { lcd_gotoxy(0,1); lcd_puts(convert); } } else { // если выше нуля sprintf(convert,"%d°",i); if (strlen(convert) <= 3) { lcd_gotoxy(0,1); lcd_puts(strcat(convert, " ")); // put_string(25,11,strcat(convert, " "),text_parametr,2); } else { lcd_gotoxy(0,1); lcd_puts(convert); // put_string(25,11,convert,text_parametr,2); } } sprintf(convert,"%.3f",(float) 1.25*((float)buffer[32]/256)); // напряжение на датчике кислорода lcd_gotoxy(1,2); lcd_puts(convert); // put_string(99,110,convert,text_parametr,2); } counter = 0; // сбрасываем counter иначе опять попадем под условие if (counter > 47) } } break; case ReadError: // если режим чтения ошибок if (StartSend == 1) { SendCommand(readDTCByStatus,8); StartSend = 0; first_draw = 0; lcd_gotoxy(0,0); lcd_putsf("ErrsStat"); } else { // !!!!!!!!!!! ответ может быть произвольной длины !!!!!!!!!!!!!! if (counter>12) { // парсим запрос + ответ unsigned char cislo_oshibok = 0; unsigned char otvet_length = 0; cislo_oshibok = buffer[12]; // смотрим число ошибок otvet_length = 13+(3*cislo_oshibok); // длинна ответа if (counter > otvet_length) { // ждем пока примутся все ошибки unsigned char i = 0; unsigned int crc = 0; for (i=8;i<otvet_length;i++) { crc = crc + buffer[i]; } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[otvet_length] == i ) { // проверяем контрольную сумму sprintf(convert,"%d",cislo_oshibok); //put_string(150,5,convert,text_parametr,1); lcd_gotoxy(0,1); lcd_puts(convert); if (cislo_oshibok != 0) { for (i=0;i < cislo_oshibok;i++) { sprintf(convert,"Р%02x%02x",buffer[(13+(i*3))],buffer[(14+(i*3))]); if (i < 6) { // put_string(5,25+(i*15),convert,0xAFE0,1); lcd_gotoxy(0,1); lcd_puts(convert); } else if (i>=6 && i<12) { // put_string(65,25+((i-6)*15),convert,0xAFE0,1); lcd_gotoxy(0,1); lcd_puts(convert); } else if (i>=12 && i<18) { // put_string(125,25+((i-12)*15),convert,0xAFE0,1); lcd_gotoxy(0,1); lcd_puts(convert); } } } } counter = 0; // сбрасываем counter иначе опять попадем под условие if (counter>12) } } } break; /* case SpeedSample: // если режим замера скорости 0-100 км/ч if (StartSend == 1) { SendCommand(readDataByLocalIdentifier_RLI_ASS,6); StartSend = 0; } else { if (counter>48) { // 6 байт запрос + 43 байта ответ (4-й байт в ответе - число байтов в посылке) unsigned char i = 0; unsigned int crc = 0; unsigned char speed = 0; for (i=6;i<48;i++) { crc = crc + buffer[i]; // считаем контрольную сумму } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[48] == i ) { // проверяем контрольную сумму speed = buffer[29]; if (speed == 0) { // если машина остановлена go = 1; // разрешаем замер скорости } if (speed > 0 && go == 1) { // начали разгоняться if (zamer_finish) { TCCR1B=0x00; } else { TCCR1B=0x04; // запустили отсчет времени if (speed >= 100) { // замер разгона до 40 км/ч zamer_finish = 1; TCCR1B=0x00; } } } sprintf(convert,"%.1f",((float) (dsec * 0.1))); // выводим время lcd_gotoxy(0,0); lcd_puts(convert); sprintf(convert,"%d",speed); // показываем текущую скорость if (strlen(convert) < 3) { //put_string(65,90,strcat(convert, " "),0xAFE0,2); lcd_gotoxy(0,1); lcd_puts(convert); } else { // put_string(65,90,convert,0xAFE0,2); lcd_gotoxy(0,1); lcd_puts(convert); } } } } break; */ default : break; } } } Данные пока что не принимает. Только отправляет. До 'StComm' не доходит
  2. По вашей подсказке, закомментировал и добавлял код. Оказалось дело было в таймерах. В итоге я поставил настройки таймеров от оригинального проекта(временно). Дисплей показывает, но только при нажатии кнопки и то кракозябры. Весь день просидел так и не нашел причину. Пробывал на железе и в проетусе запускать все то же самое. Код: /******************************************************* This program was created by the CodeWizardAVR V3.12 Advanced Automatic Program Generator © Copyright 1998-2014 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.com Project : Lada ECU Monitor Version : 1.02 Date : 09.03.2017 Author : mr_smit , inmixxx Company : Comments: Chip type : ATmega32 Program type : Application AVR Core Clock frequency: 8,000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 512 *******************************************************/ #include <mega32.h> #include <alcd.h> // Alphanumeric LCD functions #include <delay.h> #include <string.h> #include <stdio.h> // Standard Input/Output functions #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) #define Connect 1 #define ReadData 2 #define ReadError 3 #define SpeedSample 4 int mode; #define HI(x) ((x)>>8) #define LO(x) ((x)& 0xFF) char convert[32]; #define BUFFER_SIZE 200 unsigned char buffer[BUFFER_SIZE]; // приемный буффер flash unsigned char startCommunication[] = {0x81,0x10,0xf1,0x81,0x03}; flash unsigned char readDataByLocalIdentifier_RLI_ASS[] = {0x82,0x10,0xF1,0x21,0x01,0xA5}; flash unsigned char readDTCByStatus[] = {0x84,0x10,0xF1,0x18,0x00,0x00,0x00,0x9D}; flash unsigned char clearDiagnosticInformation[] = {0x83,0x10,0xf1,0x14,0x00,0x00,0x98}; // для истории // flash unsigned char startDiagnosticSession[] = {0x83,0x10,0xF1,0x10,0x81,0x0A,0x1F}; // flash unsigned char stopCommunication[] = {0x81,0x10,0xf1,0x82,0x04}; // flash unsigned char stopDiagnosticSession[] = {0x81,0x10,0xf1,0x20,0xA2}; // flash unsigned char testerPresent[] = {0x82,0x10,0xf1,0x3E,0x01,0xC2}; // flash unsigned char readDataByLocalIdentifier_RLI_FT[] = {0x82,0x10,0xF1,0x21,0x03,0xA7}; volatile bit StartSend, first_draw, go, zamer_finish; volatile unsigned char counter; volatile unsigned int ms; volatile unsigned int dsec; unsigned char Connect_Delay; // 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) { buffer[counter] = data; if (++counter == BUFFER_SIZE) { counter = 0; } } } void SendCommand (flash unsigned char *command, unsigned char length) { counter = 0; while (length--) { while(!(UCSRA & (1<<UDRE))); // ждем окончания передачи байта UDR = *command++; } } // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { // Reinitialize Timer 0 value TCNT0=0x06; if (++ms > 250) { ms = 0; StartSend = 1; // разрешаем отправку запроса через каждые 250 мс } } // Timer1 overflow interrupt service routine interrupt [TIM1_OVF] void timer1_ovf_isr(void) { // Reinitialize Timer1 value TCNT1H=0xE796 >> 8; // таймер срабатывает каждые 0,1 сек TCNT1L=0xE796 & 0xff; if (++dsec > 300) { // даем на разгон 30 сек TCCR1B=0x00; go = 0; zamer_finish = 1; } } void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port A initialization // F: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0); // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T PORTA=(0<<PORTA7) | (1<<PORTA6) | (1<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0); // Port B initialization // F: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0); // State: Bit7=0 Bit6=0 Bit5=0 Bit4=0 Bit3=0 Bit2=0 Bit1=0 Bit0=T PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0); // Port C initialization // F: Bit7=Out Bit6=Out Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out DDRC=(1<<DDC7) | (1<<DDC6) | (1<<DDC5) | (1<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0); // State: Bit7=0 Bit6=0 Bit5=0 Bit4=0 Bit3=0 Bit2=0 Bit1=0 Bit0=T PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0); // Port D initialization // F: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0); // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0); // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 250,000 kHz TCCR0=0x03; TCNT0=0x06; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 62,500 kHz // Mode: Normal top=0xFFFF // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer1 Overflow Interrupt: On // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0xE7; TCNT1L=0x96; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (1<<TOIE1) | (0<<OCIE0) | (1<<TOIE0); // External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00); MCUCSR=(0<<ISC2); // USART initialization // Communication Parameters: 8 Data, 1 Stop, No Parity // USART Receiver: On // USART Transmitter: On // USART Mode: Asynchronous // USART Baud Rate: 10400 UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM); UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8); UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL); UBRRH=0x00; UBRRL=0x2F; // Analog Comparator initialization // Analog Comparator: Off // The Analog Comparator's positive input is // connected to the AIN0 pin // The Analog Comparator's negative input is // connected to the AIN1 pin ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0); SFIOR=(0<<ACME); // ADC initialization // ADC disabled ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0); // SPI initialization // SPI disabled SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0); // TWI initialization // TWI disabled TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE); // Alphanumeric LCD initialization // Connections are specified in the // Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu: // RS - PORTC Bit 7 // RD - PORTC Bit 1 // EN - PORTC Bit 6 // D4 - PORTC Bit 5 // D5 - PORTC Bit 4 // D6 - PORTC Bit 3 // D7 - PORTC Bit 2 // Characters/line: 16 //StartSend =1; // Global enable interrupts #asm("sei") lcd_init(16); lcd_clear(); lcd_gotoxy(0,9); lcd_putsf("Run"); while (1) { // // lcd_gotoxy(0,9); // lcd_putsf("Run"); if (PINA.6 == 0) { // если нажали кнопку выбора режима delay_ms(15); if (PINA.6 == 0) { lcd_gotoxy(0,9); lcd_putsf("mode++"); mode++; // меняем режим if(mode>4){ mode=2; } TCCR1B=0x00; dsec = 0; // сбрасываем замер времени go = 0; zamer_finish = 0; //first_draw = 1; // перерисовываем экран при первом заходе в режим } } if (PINA.5 == 0) { // если нажали кнопку сброса delay_ms(15); if (PINA.5 == 0) { if (mode == ReadError) { SendCommand(clearDiagnosticInformation,7); // стираем ошибки delay_ms(500); // даём ЭБУ время на стирание ошибок // first_draw = 1; lcd_gotoxy(0,9); lcd_putsf("Rd.Err"); // перерисовываем экран } else if (mode == SpeedSample) { lcd_gotoxy(0,9); lcd_putsf("spdsamp"); TCCR1B=0x00; dsec = 0; // сбрасываем замер времени go = 0; zamer_finish = 0; // first_draw = 1; // перерисовываем экран } } } switch (mode) { // смотрим какой режим case Connect: // если только что включились => подключаемся к ЭБУ if (StartSend == 1) { // очистка дисплея lcd_gotoxy(0,0); // 0 позиция, верхняя строка lcd_putsf("Conn"); delay_ms(100); SendCommand(startCommunication,5); StartSend = 0; if (++Connect_Delay > 8) { // делаем 8 попыток подключиться lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("NO ECU"); // если нет ответа, то выводим соответствующее сообщение delay_ms(2000); // и через секунду пробуем подключиться вновь Connect_Delay = 0; } } else { lcd_gotoxy(0,9); lcd_putsf("else.c"); if (counter > 11) { // парсим запрос + ответ unsigned char i = 0; unsigned int crc = 0; for (i=5;i<11;i++) { // запрос + ответ = 12 байт crc = crc + buffer[i]; // считаем контрольную сумму } i = crc & 0xFF; // берем 2 младших разряда lcd_gotoxy(0,9); lcd_putsf("c>11 "); if ( buffer[11] == i ) { // проверяем контрольную сумму if ( buffer[8] == 0xC1 ) { // положительный ответ startCommunication //SendCommand(startDiagnosticSession,7); // запрашиваем диагностику, ответ не проверяем (хотя надо бы...) mode = ReadData; // переходим в режим чтения данных // first_draw = 1; } } counter = 0; // сбрасываем counter иначе опять попадем под условие if (counter > 11) } } break; case ReadData: lcd_gotoxy(0,9); lcd_putsf("Rd.Dat"); if (StartSend == 1) { lcd_gotoxy(0,9); lcd_putsf("StartS"); SendCommand(readDataByLocalIdentifier_RLI_ASS,6); StartSend = 0; } else { if (counter>48) { // 6 байт запрос + 43 байта ответ (4-й байт в ответе - число байтов в посылке) unsigned char i = 0; unsigned int crc = 0; //unsigned char drossel = 0; for (i=6;i<48;i++) { crc = crc + buffer[i]; // считаем контрольную сумму } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[48] == i ) { // проверяем контрольную сумму i = buffer[20] - 0x28; // вычисляем температуру двигателя if (i & 0x80) { // если она ниже нуля i = 256 - i; sprintf(convert,"-%d°",i); if (strlen(convert) <= 3) { // стираем лишнее справа от параметра в случае если он стал одинарным или двойным lcd_gotoxy(0,1); lcd_puts(strcat(convert, " ")); // выводим надпись в указанных координатах } else { lcd_gotoxy(0,1); lcd_puts(convert); } } else { // если выше нуля sprintf(convert,"%d°",i); if (strlen(convert) <= 3) { lcd_gotoxy(0,1); lcd_puts(strcat(convert, " ")); // put_string(25,11,strcat(convert, " "),text_parametr,2); } else { lcd_gotoxy(0,1); lcd_puts(convert); // put_string(25,11,convert,text_parametr,2); } } sprintf(convert,"%.3f",(float) 1.25*((float)buffer[32]/256)); // напряжение на датчике кислорода lcd_gotoxy(1,2); lcd_puts(convert); // put_string(99,110,convert,text_parametr,2); } counter = 0; // сбрасываем counter иначе опять попадем под условие if (counter > 47) } } break; case ReadError: // если режим чтения ошибок if (StartSend == 1) { SendCommand(readDTCByStatus,8); StartSend = 0; first_draw = 0; lcd_gotoxy(0,0); lcd_putsf("Errs"); } else { // !!!!!!!!!!! ответ может быть произвольной длины !!!!!!!!!!!!!! if (counter>12) { // парсим запрос + ответ unsigned char cislo_oshibok = 0; unsigned char otvet_length = 0; cislo_oshibok = buffer[12]; // смотрим число ошибок otvet_length = 13+(3*cislo_oshibok); // длинна ответа if (counter > otvet_length) { // ждем пока примутся все ошибки unsigned char i = 0; unsigned int crc = 0; for (i=8;i<otvet_length;i++) { crc = crc + buffer[i]; } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[otvet_length] == i ) { // проверяем контрольную сумму sprintf(convert,"%d",cislo_oshibok); //put_string(150,5,convert,text_parametr,1); lcd_gotoxy(0,1); lcd_puts(convert); if (cislo_oshibok != 0) { for (i=0;i < cislo_oshibok;i++) { sprintf(convert,"Р%02x%02x",buffer[(13+(i*3))],buffer[(14+(i*3))]); if (i < 6) { // put_string(5,25+(i*15),convert,0xAFE0,1); lcd_gotoxy(0,1); lcd_puts(convert); } else if (i>=6 && i<12) { // put_string(65,25+((i-6)*15),convert,0xAFE0,1); lcd_gotoxy(0,1); lcd_puts(convert); } else if (i>=12 && i<18) { // put_string(125,25+((i-12)*15),convert,0xAFE0,1); lcd_gotoxy(0,1); lcd_puts(convert); } } } } counter = 0; // сбрасываем counter иначе опять попадем под условие if (counter>12) } } } break; case SpeedSample: // если режим замера скорости 0-100 км/ч if (StartSend == 1) { SendCommand(readDataByLocalIdentifier_RLI_ASS,6); StartSend = 0; } else { if (counter>48) { // 6 байт запрос + 43 байта ответ (4-й байт в ответе - число байтов в посылке) unsigned char i = 0; unsigned int crc = 0; unsigned char speed = 0; for (i=6;i<48;i++) { crc = crc + buffer[i]; // считаем контрольную сумму } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[48] == i ) { // проверяем контрольную сумму speed = buffer[29]; if (speed == 0) { // если машина остановлена go = 1; // разрешаем замер скорости } if (speed > 0 && go == 1) { // начали разгоняться if (zamer_finish) { TCCR1B=0x00; } else { TCCR1B=0x04; // запустили отсчет времени if (speed >= 100) { // замер разгона до 40 км/ч zamer_finish = 1; TCCR1B=0x00; } } } sprintf(convert,"%.1f",((float) (dsec * 0.1))); // выводим время lcd_gotoxy(0,0); lcd_puts(convert); sprintf(convert,"%d",speed); // показываем текущую скорость if (strlen(convert) < 3) { //put_string(65,90,strcat(convert, " "),0xAFE0,2); lcd_gotoxy(0,1); lcd_puts(convert); } else { // put_string(65,90,convert,0xAFE0,2); lcd_gotoxy(0,1); lcd_puts(convert); } } } } break; default : break; } } } 123456789.DSN Lada ECU monitor.hex
  3. Немного поправил, но все равно на дисплее ничего( и com порт молчит /******************************************************* This program was created by the CodeWizardAVR V3.12 Advanced Automatic Program Generator © Copyright 1998-2014 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.com Project : Lada ECU Monitor Version : 1.02 Date : 09.03.2017 Author : mr_smit , inmixxx Company : Comments: Chip type : ATmega32 Program type : Application AVR Core Clock frequency: 8,000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 512 *******************************************************/ #include <mega32.h> #include <alcd.h> // Alphanumeric LCD functions #include <delay.h> #include <string.h> #include <stdio.h> // Standard Input/Output functions #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) #define Connect 1 #define ReadData 2 #define ReadError 3 #define SpeedSample 4 int mode; //#define HI(x) ((x)>>8) //#define LO(x) ((x)& 0xFF) //unsigned int svetlii_color = 0x1A12; // цвет заднего фона (светлый) //unsigned int temnii_color = 0x218E; // цвет заднего фона (темный) //unsigned int text_parametr = 0xFFE0; // цвет параметров //unsigned int text_tablo = 0xFFFF; // цвет надписей char convert[32]; #define BUFFER_SIZE 200 unsigned char buffer[BUFFER_SIZE]; // приемный буффер flash unsigned char startCommunication[] = {0x81,0x10,0xf1,0x81,0x03}; flash unsigned char readDataByLocalIdentifier_RLI_ASS[] = {0x82,0x10,0xF1,0x21,0x01,0xA5}; flash unsigned char readDTCByStatus[] = {0x84,0x10,0xF1,0x18,0x00,0x00,0x00,0x9D}; flash unsigned char clearDiagnosticInformation[] = {0x83,0x10,0xf1,0x14,0x00,0x00,0x98}; // для истории // flash unsigned char startDiagnosticSession[] = {0x83,0x10,0xF1,0x10,0x81,0x0A,0x1F}; // flash unsigned char stopCommunication[] = {0x81,0x10,0xf1,0x82,0x04}; // flash unsigned char stopDiagnosticSession[] = {0x81,0x10,0xf1,0x20,0xA2}; // flash unsigned char testerPresent[] = {0x82,0x10,0xf1,0x3E,0x01,0xC2}; // flash unsigned char readDataByLocalIdentifier_RLI_FT[] = {0x82,0x10,0xF1,0x21,0x03,0xA7}; volatile bit StartSend, first_draw, go, zamer_finish; volatile unsigned char counter; volatile unsigned int ms; volatile unsigned int dsec; //unsigned char Connect_Delay; // 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) { buffer[counter] = data; if (++counter == BUFFER_SIZE) { counter = 0; } } } void SendCommand (flash unsigned char *command, unsigned char length) { counter = 0; while (length--) { while(!(UCSRA & (1<<UDRE))); // ждем окончания передачи байта UDR = *command++; } } // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { // Reinitialize Timer 0 value TCNT0=0x06; if (++ms > 250) { ms = 0; StartSend = 1; // разрешаем отправку запроса через каждые 250 мс } } // Timer1 overflow interrupt service routine interrupt [TIM1_OVF] void timer1_ovf_isr(void) { // Reinitialize Timer1 value TCNT1H=0xE796 >> 8; // таймер срабатывает каждые 0,1 сек TCNT1L=0xE796 & 0xff; if (++dsec > 300) { // даем на разгон 30 сек TCCR1B=0x00; go = 0; zamer_finish = 1; } } void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port A initialization // F: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0); // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0); // Port B initialization // F: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0); // State: Bit7=0 Bit6=0 Bit5=0 Bit4=0 Bit3=0 Bit2=0 Bit1=0 Bit0=T PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0); // Port C initialization // F: Bit7=Out Bit6=Out Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out DDRC=(1<<DDC7) | (1<<DDC6) | (1<<DDC5) | (1<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0); // State: Bit7=0 Bit6=0 Bit5=0 Bit4=0 Bit3=0 Bit2=0 Bit1=0 Bit0=T PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0); // Port D initialization // F: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0); // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0); // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 125,000 kHz // Mode: Normal top=0xFF // OC0 output: Disconnected // Timer Period: 1 ms //TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (0<<CS02) | (1<<CS01) | (1<<CS00); //TCNT0=0x83; //OCR0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 31,250 kHz // Mode: Normal top=0xFFFF // OC1A output: Disconnected // OC1B output: Disconnected // Noise Canceler: Off // Input Capture on Falling Edge // Timer Period: 1 s // Timer1 Overflow Interrupt: On // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10); TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (1<<CS12) | (0<<CS11) | (0<<CS10); TCNT1H=0x85; TCNT1L=0xEE; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (1<<TOIE1) | (0<<OCIE0) | (1<<TOIE0); // External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00); MCUCSR=(0<<ISC2); // USART initialization // Communication Parameters: 8 Data, 1 Stop, No Parity // USART Receiver: On // USART Transmitter: On // USART Mode: Asynchronous // USART Baud Rate: 10400 UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM); UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8); UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL); UBRRH=0x00; UBRRL=0x2F; // Analog Comparator initialization // Analog Comparator: Off // The Analog Comparator's positive input is // connected to the AIN0 pin // The Analog Comparator's negative input is // connected to the AIN1 pin ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0); SFIOR=(0<<ACME); // ADC initialization // ADC disabled ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0); // SPI initialization // SPI disabled SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0); // TWI initialization // TWI disabled TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE); // Alphanumeric LCD initialization // Connections are specified in the // Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu: // RS - PORTC Bit 7 // RD - PORTC Bit 1 // EN - PORTC Bit 6 // D4 - PORTC Bit 5 // D5 - PORTC Bit 4 // D6 - PORTC Bit 3 // D7 - PORTC Bit 2 // Characters/line: 16 lcd_init(16); // Global enable interrupts #asm("sei") while (1) lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Test"); { if (PIND.3 == 0) { // если нажали кнопку выбора режима delay_ms(15); if (PIND.3 == 0) { mode++; // меняем режим if(mode>4){ mode=2; } TCCR1B=0x00; dsec = 0; // сбрасываем замер времени go = 0; zamer_finish = 0; first_draw = 1; // перерисовываем экран при первом заходе в режим } } } if (PIND.4 == 0) { // если нажали кнопку сброса delay_ms(15); if (PIND.4 == 0) { if (mode == ReadError) { SendCommand(clearDiagnosticInformation,7); // стираем ошибки delay_ms(500); // даём ЭБУ время на стирание ошибок first_draw = 1; // перерисовываем экран } else if (mode == SpeedSample) { TCCR1B=0x00; dsec = 0; // сбрасываем замер времени go = 0; zamer_finish = 0; first_draw = 1; // перерисовываем экран } } } switch (mode) { // смотрим какой режим case Connect: // если только что включились => подключаемся к ЭБУ if (StartSend == 1) { lcd_clear(); // очистка дисплея lcd_gotoxy(0,0); // 0 позиция, верхняя строка lcd_putsf("Conn"); delay_ms(100); SendCommand(startCommunication,5); StartSend = 0; /*if (++Connect_Delay > 8) { // делаем 8 попыток подключиться put_string(28,60,"НЕТ СВЯЗИ С ЭБУ",0xAFE0,1); // если нет ответа, то выводим соответствующее сообщение delay_ms(2000); // и через секунду пробуем подключиться вновь Connect_Delay = 0; } */ } else { if (counter > 11) { // парсим запрос + ответ unsigned char i = 0; unsigned int crc = 0; for (i=5;i<11;i++) { // запрос + ответ = 12 байт crc = crc + buffer[i]; // считаем контрольную сумму } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[11] == i ) { // проверяем контрольную сумму if ( buffer[8] == 0xC1 ) { // положительный ответ startCommunication //SendCommand(startDiagnosticSession,7); // запрашиваем диагностику, ответ не проверяем (хотя надо бы...) mode = ReadData; // переходим в режим чтения данных first_draw = 1; } } counter = 0; // сбрасываем counter иначе опять попадем под условие if (counter > 11) } } break; case ReadData: // если режим чтения данных if (first_draw == 1) { // если перешли в этот режим, то первый раз рисуем lcd_init(16); lcd_clear(); /* put_string(-3,0,"ТЕМПЕРАТУРА",text_tablo,1); put_string(98,0,"ДРОССЕЛЬ",text_tablo,1); put_string(12,33,"ОБОРОТЫ",text_tablo,1); put_string(102,33,"РЕГ. ХХ",text_tablo,1); put_string(1,66,"НАПРЯЖЕНИЕ",text_tablo,1); put_string(106,66,"ВПРЫСК",text_tablo,1); put_string(2,99,"МАСС.РАСХ.",text_tablo,1); put_string(93,99,"ДАТЧИК О2",text_tablo,1); */ first_draw = 0; }; if (StartSend == 1) { SendCommand(readDataByLocalIdentifier_RLI_ASS,6); StartSend = 0; } else { if (counter>48) { // 6 байт запрос + 43 байта ответ (4-й байт в ответе - число байтов в посылке) unsigned char i = 0; unsigned int crc = 0; //unsigned char drossel = 0; for (i=6;i<48;i++) { crc = crc + buffer[i]; // считаем контрольную сумму } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[48] == i ) { // проверяем контрольную сумму i = buffer[20] - 0x28; // вычисляем температуру двигателя if (i & 0x80) { // если она ниже нуля i = 256 - i; sprintf(convert,"-%d°",i); if (strlen(convert) <= 3) { // стираем лишнее справа от параметра в случае если он стал одинарным или двойным lcd_gotoxy(0,1); lcd_puts(strcat(convert, " ")); // выводим надпись в указанных координатах } else { lcd_gotoxy(0,1); lcd_puts(convert); } } else { // если выше нуля sprintf(convert,"%d°",i); if (strlen(convert) <= 3) { lcd_gotoxy(0,1); lcd_puts(strcat(convert, " ")); // put_string(25,11,strcat(convert, " "),text_parametr,2); //put_string(25,11,strcat(" ", convert),text_parametr,2); } else { // put_string(25,11,convert,text_parametr,2); lcd_gotoxy(0,1); lcd_puts(convert); } } } case ReadError: // если режим чтения ошибок if (first_draw == 1) { //fill_screen(bgcolor); // put_string(5,5,"КОЛИЧЕСТВО ОШИБОК:",text_tablo,1); //first_draw = 0; lcd_gotoxy(0,0); lcd_putsf("Errs"); lcd_clear(); } if (StartSend == 1) { SendCommand(readDTCByStatus,8); StartSend = 0; } else { // !!!!!!!!!!! ответ может быть произвольной длины !!!!!!!!!!!!!! if (counter>12) { // парсим запрос + ответ unsigned char cislo_oshibok = 0; unsigned char otvet_length = 0; cislo_oshibok = buffer[12]; // смотрим число ошибок otvet_length = 13+(3*cislo_oshibok); // длинна ответа if (counter > otvet_length) { // ждем пока примутся все ошибки unsigned char i = 0; unsigned int crc = 0; for (i=8;i<otvet_length;i++) { crc = crc + buffer[i]; } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[otvet_length] == i ) { // проверяем контрольную сумму sprintf(convert,"%d",cislo_oshibok); //put_string(150,5,convert,text_parametr,1); lcd_gotoxy(0,1); lcd_puts(convert); if (cislo_oshibok != 0) { for (i=0;i < cislo_oshibok;i++) { sprintf(convert,"Р%02x%02x",buffer[(13+(i*3))],buffer[(14+(i*3))]); if (i < 6) { // put_string(5,25+(i*15),convert,0xAFE0,1); lcd_gotoxy(0,1); lcd_puts(convert); } else if (i>=6 && i<12) { // put_string(65,25+((i-6)*15),convert,0xAFE0,1); lcd_gotoxy(0,1); lcd_puts(convert); } else if (i>=12 && i<18) { // put_string(125,25+((i-12)*15),convert,0xAFE0,1); lcd_gotoxy(0,1); lcd_puts(convert); } } } } counter = 0; // сбрасываем counter иначе опять попадем под условие if (counter>12) } } } break; } } } } /* case SpeedSample: // если режим замера скорости 0-100 км/ч if (first_draw == 1) { fill_screen(bgcolor); put_string(15,5,"РАЗГОН 0-100 КМ/Ч",text_tablo,1); put_string(65,25,"0.0",0xAFE0,2); put_string(52,70,"СКОРОСТЬ",text_tablo,1); first_draw = 0; } if (StartSend == 1) { SendCommand(readDataByLocalIdentifier_RLI_ASS,6); StartSend = 0; } else { if (counter>48) { // 6 байт запрос + 43 байта ответ (4-й байт в ответе - число байтов в посылке) unsigned char i = 0; unsigned int crc = 0; unsigned char speed = 0; for (i=6;i<48;i++) { crc = crc + buffer[i]; // считаем контрольную сумму } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[48] == i ) { // проверяем контрольную сумму speed = buffer[29]; if (speed == 0) { // если машина остановлена go = 1; // разрешаем замер скорости } if (speed > 0 && go == 1) { // начали разгоняться if (zamer_finish) { TCCR1B=0x00; } else { TCCR1B=0x04; // запустили отсчет времени if (speed >= 100) { // замер разгона до 40 км/ч zamer_finish = 1; TCCR1B=0x00; } } } sprintf(convert,"%.1f",((float) (dsec * 0.1))); // выводим время put_string(65,25,convert,0xAFE0,2); sprintf(convert,"%d",speed); // показываем текущую скорость if (strlen(convert) < 3) { put_string(65,90,strcat(convert, " "),0xAFE0,2); } else { put_string(65,90,convert,0xAFE0,2); } } } } break; default : break;*/
  4. Сделал для проверки дисплея отдельный проект - работает. Походу программка зависает в каком-то месте
  5. Порты задавал в Project - Configure и в CodeWizardAVR
  6. Ребят, кому не сложно, гляньте пожалуйста на код. Работаю обычно на Bascom AVR, c языком С столкнулся впервые. Захотел перевести Бортовой компьютер пользователя @mr_smit (ссылка на страницу http://cxem.net/avto/electronics/4-116.php) на символьный дисплей winstar. Танцами с бубном пытаюсь переделать код. Вроде и ошибок нет, прошил контроллер, но ничего не выводит. И еще у меня схема без кварцевого резонатора (работает на 8Мгц). Таймеры перевел вроде #include <mega32.h> // Alphanumeric LCD functions //#include <alcd.h> #include <alcd.h> // Standard Input/Output functions #include <stdio.h> #include <delay.h> #include <string.h> #include <stdio.h> // SPI functions #include <spi.h> #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) #define Connect 1 #define ReadData 2 #define ReadError 3 #define SpeedSample 4 int mode; char convert[32]; #define BUFFER_SIZE 200 unsigned char buffer[BUFFER_SIZE]; // приемный буффер flash unsigned char startCommunication[] = {0x81,0x10,0xf1,0x81,0x03}; flash unsigned char readDataByLocalIdentifier_RLI_ASS[] = {0x82,0x10,0xF1,0x21,0x01,0xA5}; flash unsigned char readDTCByStatus[] = {0x84,0x10,0xF1,0x18,0x00,0x00,0x00,0x9D}; flash unsigned char clearDiagnosticInformation[] = {0x83,0x10,0xf1,0x14,0x00,0x00,0x98}; // для истории // flash unsigned char startDiagnosticSession[] = {0x83,0x10,0xF1,0x10,0x81,0x0A,0x1F}; // flash unsigned char stopCommunication[] = {0x81,0x10,0xf1,0x82,0x04}; // flash unsigned char stopDiagnosticSession[] = {0x81,0x10,0xf1,0x20,0xA2}; // flash unsigned char testerPresent[] = {0x82,0x10,0xf1,0x3E,0x01,0xC2}; // flash unsigned char readDataByLocalIdentifier_RLI_FT[] = {0x82,0x10,0xF1,0x21,0x03,0xA7}; volatile bit StartSend, first_draw, go, zamer_finish; volatile unsigned char counter; volatile unsigned int ms; volatile unsigned int dsec; //unsigned char Connect_Delay; // 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) { buffer[counter] = data; if (++counter == BUFFER_SIZE) { counter = 0; } } } void SendCommand (flash unsigned char *command, unsigned char length) { counter = 0; while (length--) { while(!(UCSRA & (1<<UDRE))); // ждем окончания передачи байта UDR = *command++; } } // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { // Reinitialize Timer 0 value TCNT0=0x06; if (++ms > 250) { ms = 0; StartSend = 1; // разрешаем отправку запроса через каждые 250 мс } } // Timer1 overflow interrupt service routine interrupt [TIM1_OVF] void timer1_ovf_isr(void) { // Reinitialize Timer1 value TCNT1H=0xE796 >> 8; // таймер срабатывает каждые 0,1 сек TCNT1L=0xE796 & 0xff; if (++dsec > 300) { // даем на разгон 30 сек TCCR1B=0x00; go = 0; zamer_finish = 1; } } void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port A initialization // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0); // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0); // Port B initialization // Function: Bit7=Out Bit6=In Bit5=Out Bit4=Out Bit3=In Bit2=In Bit1=In Bit0=In DDRB=(1<<DDB7) | (0<<DDB6) | (1<<DDB5) | (1<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0); // State: Bit7=0 Bit6=T Bit5=0 Bit4=0 Bit3=T Bit2=T Bit1=T Bit0=T PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0); // Port C initialization // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0); // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0); // Port D initialization // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0); // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0); // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 125,000 kHz // Mode: Normal top=0xFF // OC0 output: Disconnected // Timer Period: 1 ms TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (0<<CS02) | (1<<CS01) | (1<<CS00); TCNT0=0x83; OCR0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 31,250 kHz // Mode: Normal top=0xFFFF // OC1A output: Disconnected // OC1B output: Disconnected // Noise Canceler: Off // Input Capture on Falling Edge // Timer Period: 1 s // Timer1 Overflow Interrupt: On // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10); TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (1<<CS12) | (0<<CS11) | (0<<CS10); TCNT1H=0x85; TCNT1L=0xEE; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer2 Stopped // Mode: Normal top=0xFF // OC2 output: Disconnected ASSR=0<<AS2; TCCR2=(0<<PWM2) | (0<<COM21) | (0<<COM20) | (0<<CTC2) | (0<<CS22) | (0<<CS21) | (0<<CS20); TCNT2=0x00; OCR2=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (1<<TOIE1) | (0<<OCIE0) | (1<<TOIE0); // External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00); MCUCSR=(0<<ISC2); // USART initialization // Communication Parameters: 8 Data, 1 Stop, No Parity // USART Receiver: On // USART Transmitter: On // USART Mode: Asynchronous // USART Baud Rate: 10400 UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM); UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8); UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL); UBRRH=0x00; UBRRL=0x2F; // Analog Comparator initialization // Analog Comparator: Off // The Analog Comparator's positive input is // connected to the AIN0 pin // The Analog Comparator's negative input is // connected to the AIN1 pin ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0); SFIOR=(0<<ACME); // ADC initialization // ADC disabled ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0); // SPI initialization // SPI Type: Master // SPI Clock Rate: 2*2000,000 kHz // SPI Clock Phase: Cycle Start // SPI Clock Polarity: Low // SPI Data Order: MSB First SPCR=(0<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0); SPSR=(1<<SPI2X); // TWI initialization // TWI disabled TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE); // Alphanumeric LCD initialization // Connections are specified in the // Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu: // RS - PORTC Bit 7 // RD - PORTC Bit 1 // EN - PORTC Bit 6 // D4 - PORTC Bit 2 // D5 - PORTC Bit 3 // D6 - PORTB Bit 4 // D7 - PORTC Bit 5 // Characters/line: 16 lcd_init(16); // Global enable interrupts #asm("sei") while (1) { if (PIND.3 == 0) { // если нажали кнопку выбора режима delay_ms(15); if (PIND.3 == 0) { mode++; // меняем режим if(mode>4){ mode=2; } TCCR1B=0x00; dsec = 0; // сбрасываем замер времени go = 0; zamer_finish = 0; first_draw = 1; // перерисовываем экран при первом заходе в режим } } } if (PIND.4 == 0) { // если нажали кнопку сброса delay_ms(15); if (PIND.4 == 0) { if (mode == ReadError) { SendCommand(clearDiagnosticInformation,7); // стираем ошибки delay_ms(500); // даём ЭБУ время на стирание ошибок first_draw = 1; // перерисовываем экран } else if (mode == SpeedSample) { TCCR1B=0x00; dsec = 0; // сбрасываем замер времени go = 0; zamer_finish = 0; first_draw = 1; // перерисовываем экран } } } switch (mode) { // смотрим какой режим case Connect: // если только что включились => подключаемся к ЭБУ if (StartSend == 1) { lcd_clear(); // очистка дисплея lcd_gotoxy(0,0); // 0 позиция, верхняя строка lcd_putsf("Conn"); delay_ms(100); SendCommand(startCommunication,5); StartSend = 0; /*if (++Connect_Delay > 8) { // делаем 8 попыток подключиться put_string(28,60,"НЕТ СВЯЗИ С ЭБУ",0xAFE0,1); // если нет ответа, то выводим соответствующее сообщение delay_ms(2000); // и через секунду пробуем подключиться вновь Connect_Delay = 0; } */ } else { if (counter > 11) { // парсим запрос + ответ unsigned char i = 0; unsigned int crc = 0; for (i=5;i<11;i++) { // запрос + ответ = 12 байт crc = crc + buffer[i]; // считаем контрольную сумму } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[11] == i ) { // проверяем контрольную сумму if ( buffer[8] == 0xC1 ) { // положительный ответ startCommunication //SendCommand(startDiagnosticSession,7); // запрашиваем диагностику, ответ не проверяем (хотя надо бы...) mode = ReadData; // переходим в режим чтения данных first_draw = 1; } } counter = 0; // сбрасываем counter иначе опять попадем под условие if (counter > 11) } } break; case ReadData: // если режим чтения данных if (first_draw == 1) { // если перешли в этот режим, то первый раз рисуем lcd_clear(); /* put_string(-3,0,"ТЕМПЕРАТУРА",text_tablo,1); put_string(98,0,"ДРОССЕЛЬ",text_tablo,1); put_string(12,33,"ОБОРОТЫ",text_tablo,1); put_string(102,33,"РЕГ. ХХ",text_tablo,1); put_string(1,66,"НАПРЯЖЕНИЕ",text_tablo,1); put_string(106,66,"ВПРЫСК",text_tablo,1); put_string(2,99,"МАСС.РАСХ.",text_tablo,1); put_string(93,99,"ДАТЧИК О2",text_tablo,1); */ first_draw = 0; }; if (StartSend == 1) { SendCommand(readDataByLocalIdentifier_RLI_ASS,6); StartSend = 0; } else { if (counter>48) { // 6 байт запрос + 43 байта ответ (4-й байт в ответе - число байтов в посылке) unsigned char i = 0; unsigned int crc = 0; //unsigned char drossel = 0; for (i=6;i<48;i++) { crc = crc + buffer[i]; // считаем контрольную сумму } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[48] == i ) { // проверяем контрольную сумму i = buffer[20] - 0x28; // вычисляем температуру двигателя if (i & 0x80) { // если она ниже нуля i = 256 - i; sprintf(convert,"-%d°",i); if (strlen(convert) <= 3) { // стираем лишнее справа от параметра в случае если он стал одинарным или двойным lcd_gotoxy(0,1); lcd_puts(strcat(convert, " ")); // выводим надпись в указанных координатах } else { lcd_gotoxy(0,1); lcd_puts(convert); } } else { // если выше нуля sprintf(convert,"%d°",i); if (strlen(convert) <= 3) { lcd_gotoxy(0,1); lcd_puts(strcat(convert, " ")); // put_string(25,11,strcat(convert, " "),text_parametr,2); //put_string(25,11,strcat(" ", convert),text_parametr,2); } else { // put_string(25,11,convert,text_parametr,2); lcd_gotoxy(0,1); lcd_puts(convert); } } case ReadError: // если режим чтения ошибок if (first_draw == 1) { //fill_screen(bgcolor); // put_string(5,5,"КОЛИЧЕСТВО ОШИБОК:",text_tablo,1); //first_draw = 0; lcd_gotoxy(0,0); lcd_putsf("Errs"); lcd_clear(); } if (StartSend == 1) { SendCommand(readDTCByStatus,8); StartSend = 0; } else { // !!!!!!!!!!! ответ может быть произвольной длины !!!!!!!!!!!!!! if (counter>12) { // парсим запрос + ответ unsigned char cislo_oshibok = 0; unsigned char otvet_length = 0; cislo_oshibok = buffer[12]; // смотрим число ошибок otvet_length = 13+(3*cislo_oshibok); // длинна ответа if (counter > otvet_length) { // ждем пока примутся все ошибки unsigned char i = 0; unsigned int crc = 0; for (i=8;i<otvet_length;i++) { crc = crc + buffer[i]; } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[otvet_length] == i ) { // проверяем контрольную сумму sprintf(convert,"%d",cislo_oshibok); //put_string(150,5,convert,text_parametr,1); lcd_gotoxy(0,1); lcd_puts(convert); if (cislo_oshibok != 0) { for (i=0;i < cislo_oshibok;i++) { sprintf(convert,"Р%02x%02x",buffer[(13+(i*3))],buffer[(14+(i*3))]); if (i < 6) { // put_string(5,25+(i*15),convert,0xAFE0,1); lcd_gotoxy(0,1); lcd_puts(convert); } else if (i>=6 && i<12) { // put_string(65,25+((i-6)*15),convert,0xAFE0,1); lcd_gotoxy(0,1); lcd_puts(convert); } else if (i>=12 && i<18) { // put_string(125,25+((i-12)*15),convert,0xAFE0,1); lcd_gotoxy(0,1); lcd_puts(convert); } } } } counter = 0; // сбрасываем counter иначе опять попадем под условие if (counter>12) } } } } } } } } // break; /*case SpeedSample: // если режим замера скорости 0-100 км/ч if (first_draw == 1) { fill_screen(bgcolor); put_string(15,5,"РАЗГОН 0-100 КМ/Ч",text_tablo,1); put_string(65,25,"0.0",0xAFE0,2); put_string(52,70,"СКОРОСТЬ",text_tablo,1); first_draw = 0; } if (StartSend == 1) { SendCommand(readDataByLocalIdentifier_RLI_ASS,6); StartSend = 0; } else { if (counter>48) { // 6 байт запрос + 43 байта ответ (4-й байт в ответе - число байтов в посылке) unsigned char i = 0; unsigned int crc = 0; unsigned char speed = 0; for (i=6;i<48;i++) { crc = crc + buffer[i]; // считаем контрольную сумму } i = crc & 0xFF; // берем 2 младших разряда if ( buffer[48] == i ) { // проверяем контрольную сумму speed = buffer[29]; if (speed == 0) { // если машина остановлена go = 1; // разрешаем замер скорости } if (speed > 0 && go == 1) { // начали разгоняться if (zamer_finish) { TCCR1B=0x00; } else { TCCR1B=0x04; // запустили отсчет времени if (speed >= 100) { // замер разгона до 40 км/ч zamer_finish = 1; TCCR1B=0x00; } } } sprintf(convert,"%.1f",((float) (dsec * 0.1))); // выводим время put_string(65,25,convert,0xAFE0,2); sprintf(convert,"%d",speed); // показываем текущую скорость if (strlen(convert) < 3) { put_string(65,90,strcat(convert, " "),0xAFE0,2); } else { put_string(65,90,convert,0xAFE0,2); } } } } break; default : break; } } } */
  7. Ребят, а можно ли использовать шим вместо переменника в БУК? Если да, то как его реализовать?
  8. Омыватель конечно же есть, подключен омыватель от заднего стекла на фары.
  9. Ну хорошо. Сожно сделать хотябы кивок и установка на уровень по массе нагруженности. На фарах стоят линзы и я никого не слеплю!!! Ниразу не моргали встречные. И представители дорожных служб не докапывались. Хочу все узаконить. Родные галогены на "Киржаче" светят очень слабо. У кого ваз 2110-12 с такими фарами, тот меня поймет. Народ ставил, и блок управления ведет себя не очень. все время подергивается и это не есть гуд Нкоторые так и делают. Например такой датчик идет в комплекте с автокорректором "Силичъ зенит"
  10. Ребят, сегодня прикупил электромеханический корректор фар ЭМКФ11 с блоком управления БУК-021 на ваз 2112 Хочу сам блок управления сделать на микроконтроллере avr. раньше всеми этими контроллерами баловался на bascom avr и после армии и двух лет работы на заводе уже все позабыл. язык С вообще не понимаю. Принцип работы блока управления: на моторредукторах имеются переменные резисторы положения штока. а блок управления просто сравнивает с шаговым резистором на ручке управления и двигает моторредуктор. Схему укреплю. Нужно мне что? - Полная замена электронного блока управления(или внедрение его вместо шагового резистора на блоке) на микроконтроллерный для постановки ксенона. То есть мы будем регулировать положением моторредукторов через переменный резистор установленный на днище и закрепленный на заднюю балку. просто если поставить переменник вместо шаговика, схема будет постоянно дергаться на кочках. а это включил зажигание - фары "кивнули " и установились на уровень который зависит от того резистора закрепленного на днище то есть от загруженности автомобиля и схема отключилась на 10 мин. Может у кого-то есть похожие кусочки кодов ? или ссылки на источник? с гуглом уже вожусь 2е суток ничего найти не могу толком.
×
×
  • Создать...