Коллеги, помогите! Появилось у меня хобби - начал с Ардуино UNO и теперь дорос до контроллера ATtiny441 + Atmel Studio 7. Играюсь с домашне-дачной автоматизацией ... Задача очень простая: удаленно посылая телеграммы по RS-485 (протокол ModBus RTU) управлять с компьютера периферией и отвечать компьютеру о своем состоянии. Начал писать код: Код: Код (C++): #define F_CPU 1000000UL #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #define BUFFER_SIZE 128 #define StartTransmit_SET_OUTPUT DDRA |= (1 << 0) #define StartTransmit_LOW PORTA |= (1 << 0) #define StartTransmit_HIGH PORTA &= ~(1 << 0) #define LED_SET_OUTPUT DDRA |= (1 << 4) #define LED_LOW PORTA |= (1 << 4) #define LED_HIGH PORTA &= ~(1 << 4) volatile unsigned char slaveID = 50; unsigned char frame[BUFFER_SIZE]; unsigned char funktion=1; bool broadcastFlag=0; void USART_Init() { UBRR0H = 0; UBRR0L = 6; UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0); UCSR0C = (1<<USBS0)|(3<<UCSZ00); } unsigned int calculateCRC(uint8_t bufferSize) { unsigned int temp, temp2, flag; temp = 0xFFFF; for (unsigned char i = 0; i < bufferSize; i++) { temp = temp ^ frame[i]; for (unsigned char j = 1; j <= 8; j++) { flag = temp & 0x0001; temp >>= 1; if (flag) temp ^= 0xA001; } } temp2 = temp >> 8; temp = (temp << 8) | temp2; temp &= 0xFFFF; return temp; } void USART_Transmit( unsigned char data ) { StartTransmit_LOW; _delay_ms(5); while ( !( UCSR0A & (1<<UDRE0)) ); UDR0 = data; _delay_ms(5); StartTransmit_HIGH; _delay_ms(5); } void USART_Transmit_String() { int i=0; unsigned char c = frame[0]; while(c != '\0') { c = frame[i]; if(c!='\0') {USART_Transmit(c);} i++; } } void exceptionResponse(unsigned char exception) { if (!broadcastFlag) { frame[0] = slaveID; frame[1] = (funktion | 0x80); frame[2] = exception; unsigned int crc16 = calculateCRC(3); frame[3] = crc16 >> 8; frame[4] = crc16 & 0xFF; USART_Transmit_String(); } } ISR (USART0_RX_vect) { while ( !(UCSR0A & (1<<RXC0)) ); slaveID = UDR0; } int main(void) { USART_Init(); StartTransmit_SET_OUTPUT; LED_SET_OUTPUT; LED_LOW; sei(); while(1) { exceptionResponse(2); _delay_ms(5000); } } и столкнулся со следующей хренью: вбиваю в Terminal Window (встроенный терминал в Atmel Studio 7) число 33 - по указанному выше алгоритму если в буфере что то появилось, то переменная slaveID становится этим. Но она этим становится в хаотичном порядке: может так: 33 81 02 60 5e - и это правильно, она 33, а может так: b3 81 02 61 b6 - это когда первый бит у тройки заменен на 1. Причем непонятно с чем это связано. Вроде вбиваю в поле Send терминала 33, все честно, но результат на выходе ИЛИ-ИЛИ. Нет стабильности. Например та же хрень при вводе 54: 5 раз d4 81 02 d0 69, три раза 54 81 02 d1 81 Для приема в терминал использую китайский переходник с UART на RS-485 и переходник - RS-485 - USB. Если есть у кого какие мысли - помогите, пожалуйста, разобраться. Спасибо!
... если бы сыпался мусор, то да, я полностью согласен! но! либо 33, либо b3. то есть 1 бит либо 1 (что не правильно) либо (что правильно) 0. Меняется хаотично при приеме только 1 бит .......
Решено! правильно инициализировать UART в моем случае вот так: Код (C++): void USART_Init() { UBRR0H = 0; UBRR0L = 12; UCSR0A = (1 << U2X0); UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0); UCSR0C = (1<<USBS0)|(3<<UCSZ00); } Ошибок больше не ловил! Спасибо!