Здравия вам товарищи коты) Возник вопрос при изучении 9 битного варта. Смысл такой, написал программу для двух мк 168 меги, в программе они обмениваются по варту бегущими огнями (посылки 9 бит). При получении посылки сначала считываются три бита ошибок варта (FE0, DOR0, UPE0) и каждый бит выводится на свой пин индикации (светодиоды), ну и сами 9 бит посылки выводятся на порт индикации, засада в том, по принятию посылки, где установлен 9-ый бит возникает ошибка кадрирования (FE0) , как только принимается следующая посылка с нулевым значением 9-го бита флаг ошибки кадрирования сбрасывается, почему так? ниже исходник для обоих мк, в исходнике в коментах все подробно написано
Спойлер
Код:
/* ------ асинхронный (9-N-1) ------ РАБОТАЕТ --- но есть нюанс ошибки кадрирования (FE0)------- * GccApplication57.c * ----- прога для равноправных МК ---------- индикация битов ошибок (FE0, DOR0, UPE0) модуля USART0 -------- * Created: 02.06.2021 15:45:07 * Author : Admin */
// задача-организовать поочередную отправку и прием 9-ти битной посылки циклически (полудуплекс) и опросить все биты ошибок (FE0, DOR0, UPE0) модуля USART0, // затем значение каждого бита из 3 вывести на свой пин индикации и конечно же на индикацию вывести 9 бит посылки // // в программе мы изучаем 9-и битный режим передачи и хотим наблюдать на светодиодах есть ли ошибки модуля USART0 и также саму посылку хотим видеть на светодиодах, // для этого под ошибки модуля USART0 назначим такие светодиоды // (PORTD7) ---- значение (FE0) ----- Флаг ошибки кадрирования // (PORTD6) ---- значение (DOR0) ----- Флаг переполнения // (PORTD5) ---- значение (UPE0) ----- Флаг ошибки контроля четности // (PORTD3) ---------- значение 9-го бита принятой посылки // (PORTB ) ---------- 8 младших битов принятой посылки // // прога работает так, в суперцикле по прерыванию системного таймера отправляем байты бегущего огонька другому мк не читая принятые взамен байты, // затем по прерыванию завершение приема мы получаем 9-ти битную посылку и выводим все полученые биты на светодиодную индикацию (9 битов посылка и 3 бита ошибок) // получается у нас 9-и битный бегущий огонек и почему то в момент получения установленого 9-го бита у нас зажигается ошибка кадрирования бит (FE0), затем // когда в следующей посылке 9-ый бит сброшен сбрасывается и ошибка // // // // частота ядра 1 МГц , скорость = 2400 бит/с при UBRR = 25 и U2X0 = 0 таблица даташит, но мы по формуле в дефайнах вычислим (UBRR) // асинхронный USART0 ---------- (UMSEL10=0, UMSEL00=0) // отключена проверка на четность и нечетность ----- (UPM01=0, UPM00=0) // 1 стоп, 9 data, без проверки четности, асинхронный (9-N-1)
//---------- void TIMER0_init(void) // инициализация модуля таймера Т0 режим СТС прерывание и сброс по совпадению с содержимым регистра (OCR0A) { TIMSK0 = 0b00000010; // бит РВ1(OCIE0A) устанавливаем в 1, разрешения прерывания по совпадению блока А таймера /счетчика Т0 TCCR0A = 0b00000010; // биты (WGM02,WGM00) сбрасываем в 0, (WGM01) установим в 1 настройка ------- режима СТС TCCR0B = 0b00000010; // настраиваем предделитель на 8 (биты CS02=0,CS01=1,CS00=0),бит В3(WGM02) сбрасываем в 0 OCR0A = 100; // запишем 100 в регистр сравнения (OCR0A) блока А GTCCR = 0b00000001; // бит РВ0(PSRSYNC) устанавливаем в 1, Сброс предделителя TO (сбрасываем пред. в конце настроек)
} //---------- void USART0_Init_9_N_1( unsigned int ubrr) // инициализация приемопередатчика USART0. { UBRR0H = (uint8_t)(ubrr>>8); // сместив двух байтовый (ubrr) 8 раз вправо мы впишем в одно байтовый регистр (UBRR0H) старший байт UBRR0L = (uint8_t)ubrr; // запишем рассчитанное в дефайнах число в младший одно байтовый регистр скорости (UBRR0L) UCSR0B = (1<<TXEN0)|(1<<RXEN0)|(1<<RXCIE0)|(1<<UCSZ02); // разрешаем работу модуля передатчика и приемника, разрешение прерывания по завершении приема UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); // 1 стоп-бит, размер слова 9 бит (9-N-1) }
//----------
void USART_Transmit( uint16_t data ) // передаем 9 битный символ так - помещаем 9-тый бит в (TXB80), а затем записываем младшие 8 битов в (UDR0) { while ( !( UCSR0A & (1<<UDRE0)) ); // ожидаем опустошение приемного регистра if ( data & 0x0100 ) // проверяем 9 по счету бит переменной (data), если этот бит = 1, то выполняется выражение в скобках { UCSR0B |= (1<<TXB80); // устанавливаем 9 по счету бит передачи (TXB80) в 1 } else // иначе 9 по счету бит переменной (data) не равен 1, то есть = 0, то выполняется выражение в скобках { UCSR0B &= ~(1<<TXB80); // сбрасываем 9 по счету бит передачи (TXB80) в 0 } UDR0 = data; // отправляем оставшиеся 8 бит в регистр данных } //---------- uint16_t USART_Receive( void ) // прием 9-ти битной посылки в режиме (9-N-1). выдаем из функции через ретурн 2-х байтное слово { // 8-0-ой разряд ---------- младший байт посылки // 9-ой разряд --- бит (RXB80) -- 9 бит посылки // 10-ый разряд --- бит (UPE0) -- Флаг ошибки контроля четности // 11-ой разряд --- бит (DOR0) -- Флаг переполнения // 12-ий разряд --- бит (FE0) -- Флаг ошибки кадрирования while ( !(UCSR0A & (1<<RXC0)) ); // ожидаем завершения приема ( ПРИМЕНЯЕМ ЭТУ СТРОКУ, ЕСЛИ ФУНКЦИЯ РАБОТАЕТ НЕ В ПРЕРЫВАНИИ ПО ЗАВЕРШЕНИЮ ПРИЕМА)
status = UCSR0A; // считываем значение регистра статуса (UCSR0A) в переменную (status), ( тут у нас флаги FE0, DOR0, UPE0) resh = UCSR0B; // считываем значение регистра управления (UCSR0B) в переменную (resh), в нем же 9 бит (RXB80) resl = UDR0; // считываем полученый 8 битный байт данных из регистра данных (UDR0)
status = (status >> 1) & 0x0E; // сместим байт (status) на одну позицию вправо, тем самым бит (UPE0) со 2-го разряда перейдет в 1-ой, бит (DOR0) с 3-го // во 2-ый, бит (FE0) с 4-го в 3-ой, затем на байт набросим маску 0x0E и все разряды обнулятся кроме 1,2,3 в которых // теперь наши статусные биты (FE0, DOR0, UPE0)
if (resh & 0x02) // проверяем 1 разряд переменной (resh) он же (RXB80) , если этот бит = 1, то выполняется выражение в скобках { status |= (1<<0); // установить в 1 нулевой разряд переменной (status), остальные биты не трогаем } else // иначе если 1 бит переменной (resh) равен 0 , то выполняется выражение в скобках { status &= ~(1<<0); // сбросить в 0 нулевой разряд переменной (status), остальные биты не трогаем } // теперь в переменной (status) у нас биты: 0-ой разряд --- бит (RXB80) // 1-ый разряд --- бит (UPE0) // 2-ой разряд --- бит (DOR0) // 3-ий разряд --- бит (FE0)
return ((status << 8) | resl); // сместим байт (status) в старший байт двухбайтового слова и получится такая картина-- // 9-ой разряд --- бит (RXB80) -- 9 бит посылки // 10-ый разряд --- бит (UPE0) -- Флаг ошибки контроля четности // 11-ой разряд --- бит (DOR0) -- Флаг переполнения // 12-ий разряд --- бит (FE0) -- Флаг ошибки кадрирования // а в восемь остальных младших бит поместим значение из (UDR0) }
//----------
uint16_t running_light(void) // ф-ия передает в вызывающюю ф-ию бегущий огонек (при каждом вызове в переданом 9-и битном слове еденица смещается на разряд влево) { // примерно так- сначала 0b000000001, при следующем вызове 0b000000010, потом 0b000000100 и так по 0b100000000 и все заново uint16_t data = 0; // создаем и задаем значение переменной (data), static uint8_t a = 0; // создаем и задаем значение статической переменной (a), она у нас будет номером бита в нашем байте данных (data)
if (a>8) a=0; // защита от переполнения, как только (а) станет = 9 она обнулится , что бы не вылезти за размер 9 битного символа data = (1 << a); // установка еденицы в бит (а) байта (data) с затиранием остальных битов, например было (0b000000001) потом стало (0b000000010) a++ ; // инкрементируем наш номер бита в 9-ти битном слове))) return (data); // передаем в вызывающюю функцию наш байт }
//---------- ISR(USART_RX_vect) // прерывание по завершению приема {
uint16_t in_data = 0 ; // в это двухбайтовое слово будем получать данные от другого МК in_data = USART_Receive(); // получим в (in_data) нашу 9 битную посылку и статус ошибок модуля USART0
uint8_t x_low = in_data & 0xff; // обнуляем старший байт двухбайтового слова и остается значение младшего байта, которое запишем в (x_low) uint8_t x_high = (in_data >> 8); // сдвигаем старший байт в младший байт двухбайтового слова и записываем в (x_high)
if (x_high & 0x01) // проверяем 0-ой разряд переменной x_high (там у нас значение 9 бита), если этот разряд = 1, то выполним выражение в скобках { PORTD |= (1<<PORTD3); // зажгем светодиод на пине (PORTD3) } else // иначе если нулевой разряд = 0 , то выполним выражение в скобках { PORTD &= ~(1<<PORTD3); // погасим светодиод на пине (PORTD3) }
if (x_high & 0x02) // проверяем 1-ой разряд переменной x_high (там у нас значение (UPE0)), если этот разряд = 1, то выполним выражение в скобках { PORTD |= (1<<PORTD5); // зажгем светодиод на пине (PORTD5) } else // иначе если 1-ый разряд = 0 , то выполним выражение в скобках { PORTD &= ~(1<<PORTD5); // погасим светодиод на пине (PORTD5) }
if (x_high & 0x04) // проверяем 2-ой разряд переменной x_high (там у нас значение (DOR0)), если этот разряд = 1, то выполним выражение в скобках { PORTD |= (1<<PORTD6); // зажгем светодиод на пине (PORTD6) } else // иначе если 2-ой разряд = 0 , то выполним выражение в скобках { PORTD &= ~(1<<PORTD6); // погасим светодиод на пине (PORTD6) }
if (x_high & 0x01) // проверяем 3-ий разряд переменной x_high (там у нас значение (FE0)), если этот разряд = 1, то выполним выражение в скобках { PORTD |= (1<<PORTD7); // зажгем светодиод на пине (PORTD7) } else // иначе если 3-ий разряд = 0 , то выполним выражение в скобках { PORTD &= ~(1<<PORTD7); // погасим светодиод на пине (PORTD7) }
PORT_LED = x_low; // принятый младший байт выведем в порт индикации }
//---------- ISR(TIMER0_COMPA_vect) // прерывание по совпадению блока А таймера Т0 {
int main(void) { DDRD |= (1<<DDD7)|(1<<DDD6)|(1<<DDD5)|(1<<DDD3); // конфигурируем пины DDD7,DDD6,DDD5 и DDD3 на выход, на них будут 9 бит посылки и три бита ошибок ВАРТа DDR_LED = 0b11111111; // на выход ( на нем наши индикаторные светоды) TIMER0_init (); // инициализация и настройка модуля таймера Т0 USART0_Init_9_N_1(MYUBRR); // передаем рассчитанное значение скорости (MYUBRR) в блок инициализации USART0 uint16_t out_data = 0 ; // двухбайтовый символ для отправки другому мк по USART0 sei();
while (1) {
if (sis_taimer == 100) // системный таймер { out_data = running_light(); // бегущий огонек загоняем в переменную на отправку другому МК USART_Transmit (out_data); // отправляем байт другому мк sis_taimer =0; // сбросим таймер и ждем следующего тика системного таймера
} } }
_________________ глаза боятся, а руки что то не делают))
roman.com, что то не могу себе представить, что UART не используется))) сама программа работает, отправляет принимает, биты не теряются, просто хочу выяснить я где то схалтурил или такая особенность у микроконтроллеров атмеловских? ну еще правда в даташите на 168 мегу приводится такая функция приема посылки о 9 битах
Код:
unsigned int USART_Receive( void ) // Получим статус и 9-й бит, затем данные из буфера приемника { unsigned char status, resh, resl; // объявим переменные
while ( !(UCSR0A & (1<<RXC0)) ); // ожидаем завершения приема (получение данных)
status = UCSR0A; // считываем значение регистра статуса (UCSR0A) в переменную (status), ( тут у нас флаги FE0, DOR0, UPE0) resh = UCSR0B; // считываем значение регистра управления (UCSR0B) в переменную (resh), в нем же 9 по счету бит (RXB80) resl = UDR0; // считываем полученный 8 битный байт данных из регистра данных (UDR0)
if ( status & (1<<FE0)|(1<<DOR0)|(1<<UPE0) ) // проверяем установлены ли биты (FE0, DOR0, UPE0), если хоть один бит установлен, то выполняем код в скобках { return -1; // ошибка приемопередачи модуля USART0 }
resh = (resh >> 1) & 0x01; // сместим байт (resh) на одну позицию вправо, тем самым бит принимаемых данных (RXB80) с 1 позиции в байте перейдет на 0 позицию, // затем затем на этот байт набросим маску 0x01 и все разряды обнулятся кроме нулевого разряда, в нем будет значение бита (RXB80)
return ((resh << 8) | resl); // сместим бит (RXB80) в 9 по счету бит, а в восемь остальных младших бит поместим значение из (UDR0)
}
как может быть return -1 ? там же на выходе unsigned int? не понимаю.... короче я переделал эту функцию как по моему пониманию она должна работать
Код:
uint16_t USART_Receive( void ) // прием 9-ти битной посылки в режиме (9-N-1). выдаем из функции через ретурн 2-х байтное слово { // 8-0-ой разряд ---------- младший байт посылки // 9-ой разряд --- бит (RXB80) -- 9 бит посылки // 10-ый разряд --- бит (UPE0) -- Флаг ошибки контроля четности // 11-ой разряд --- бит (DOR0) -- Флаг переполнения // 12-ий разряд --- бит (FE0) -- Флаг ошибки кадрирования while ( !(UCSR0A & (1<<RXC0)) ); // ожидаем завершения приема ( ПРИМЕНЯЕМ ЭТУ СТРОКУ, ЕСЛИ ФУНКЦИЯ РАБОТАЕТ НЕ В ПРЕРЫВАНИИ ПО ЗАВЕРШЕНИЮ ПРИЕМА)
status = UCSR0A; // считываем значение регистра статуса (UCSR0A) в переменную (status), ( тут у нас флаги FE0, DOR0, UPE0) resh = UCSR0B; // считываем значение регистра управления (UCSR0B) в переменную (resh), в нем же 9 бит (RXB80) resl = UDR0; // считываем полученый 8 битный байт данных из регистра данных (UDR0)
status = (status >> 1) & 0x0E; // сместим байт (status) на одну позицию вправо, тем самым бит (UPE0) со 2-го разряда перейдет в 1-ой, бит (DOR0) с 3-го // во 2-ый, бит (FE0) с 4-го в 3-ой, затем на байт набросим маску 0x0E и все разряды обнулятся кроме 1,2,3 в которых // теперь наши статусные биты (FE0, DOR0, UPE0)
if (resh & 0x02) // проверяем 1 разряд переменной (resh) он же (RXB80) , если этот бит = 1, то выполняется выражение в скобках { status |= (1<<0); // установить в 1 нулевой разряд переменной (status), остальные биты не трогаем } else // иначе если 1 бит переменной (resh) равен 0 , то выполняется выражение в скобках { status &= ~(1<<0); // сбросить в 0 нулевой разряд переменной (status), остальные биты не трогаем } // теперь в переменной (status) у нас биты: 0-ой разряд --- бит (RXB80) // 1-ый разряд --- бит (UPE0) // 2-ой разряд --- бит (DOR0) // 3-ий разряд --- бит (FE0)
return ((status << 8) | resl); // сместим байт (status) в старший байт двухбайтового слова и получится такая картина-- // 9-ой разряд --- бит (RXB80) -- 9 бит посылки // 10-ый разряд --- бит (UPE0) -- Флаг ошибки контроля четности // 11-ой разряд --- бит (DOR0) -- Флаг переполнения // 12-ий разряд --- бит (FE0) -- Флаг ошибки кадрирования // а в восемь остальных младших бит поместим значение из (UDR0)
может дело в этом? мне правда интересно разобраться в чем тут дело , товарищи полосатые кто обладает знанием подсобите?
_________________ глаза боятся, а руки что то не делают))
Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
На си писал очень давно и не под AVR. Поэтому не особо вникал в код. Плюс не совсем понятно поставлена вами задача, которую вы пытаетесь решить; и совершенно непонятно, какие действия вы проделывали, чтобы проверить, что вы хотя бы отправляете правильный сигнал по UART. И да, вы не привели схему вашего устройства.
Попытаюсь помочь экстрасенсорно. Для начала перепроверьте все ваши инициализации. Откройте даташит на МК (оригинал) и пройдитесь по всем управляющим регистрам и явно определите инициализируемые значения для ВСЕХ регистров UART (даже для казалось бы не используемых). Ни в коем случае не доверяйте указанным в даташите значениям по умолчанию, иногда они бывают другими, я лично на это натыкался.
Про логику вашей программы я ничего сказать не могу. Для проверки сигнала вы можете сделать следующее. Выставите скорость UART такой, чтобы длительность импульсов переключения была достаточно низкочастотной. Подключите через подходящий делитель на резисторах выход UART к звуковому входу компьютера и запишите сигнал в каком-нибудь аудиоредакторе (например, Sony Sound Forge). Внимательно изучите записанный сигнал и убедитесь, что в сигнале правильная последовательность импульсов правильной длины. Важно заметить, что иногда звуковые карты (особенно при записи через микрофонный вход, а не через линейный) инвертируют фазу сигнала. Это тоже надо проверить. Если у вас есть супернавороченный цифровой осциллограф, позволяющий записать сигнал, а потом изучить его в своё удовольствие со всеми подробностями — тем лучше.
Приведённый вами код совершенно неудобочитаем. Если хотите, чтобы кто-то в него серьёзно повникал, отредактируйте его так, чтобы не было переносов комментариев через строчку. Рекомендую включить в вашем редакторе кода ограничение в 80 символов (стандартная величина), и не выпускать код за это значение. Если в настройках нет ничего подобного, то можно прикинуть величину и уменьшить окно редактирования, так чтобы его размер указывал вам ограничение.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
B@R5uk, дело в том, что в авр студии и в нотепаде код с комментариями как раз четнко в строчку со всеми пробелами и отступами, сюда вставляю и тут с переносами и тд.. В Notepad++ или в авр студии можно его открыть, чтоб аккуратным он был. это не устройство, просто тупо две 168 атмеги пересылают по 9-ти битному варту бегущий огонек, биты и байты не пропускаются, логическим анализатором в железе смотрю и на светодиодах индикации тоже вижу правильную последовательность бегущего огонька на обоих мк. задача простая, в железе проверить и изучить работу аппаратного варта на атмеге 168р. в протеусе тоже самое поведение
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 23
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения