Сегодня весь день пытался добиться надежной работы RS-485 на STM32F042 (исходники). Оказывается, это не настолько уж и тривиально, как просто поднять UART и радоваться! Так как 485 работает в полудуплексе, необходимо перед приемом/передачей выставить соответствующий уровень на ноге, контролирующей направление передачи. Выставляю — бац, косяк: сообщения "обрубаются" на последней паре символов. Оказалось, что переключать направление приемопередатчика из прерывания по окончанию передачи DMA нельзя, т.к. USART в это время еще не передал все данные. Ладно, добавляю простой конечный автомат:
void usart_proc(){
switch(st){
case SENDING:
if(txrdy) st = WAITING;
break;
case WAITING:
if(USARTX->ISR & USART_ISR_TXE){ // last byte done -> Rx
_485_Rx();
}
break;
default:
break;
}
}
И опять косяк! "\n" в конце каждой передачи отсутствует! Тут до меня дошло: ведь USART_ISR_TXE выставляется, когда буфер для отправки пуст, но это отнюдь не значит, что данные уже "уехали". Заменил этот флаг на USART_ISR_TC, и передача пошла нормально. Но тут появились проблемы с приемом: в принимающий буфер постоянно попадал какой-то мусор. Видимо, "китайские" MAX485 (хотя вроде бы эта партия покупалась у нормальных поставщиков) не закрывают полностью канал RO при подаче на ~RE единицы, либо 3.3В им не хватает!.. (схема рассчитана на MAX3485, у которых напряжение питания 3.3В, а впаял я первое, что под руку подвернулось — MAX485E, а судя по даташиту, этому 5В подавай!) В общем, проблема приема мусора тоже решилась: USART я стал включать либо только на прием, либо только на передачу, переделав макросы переключения Rx/Tx:
Зачем я отдельно Rx и Tx подключал — тоже сейчас не вспомню, ведь намного логичней было бы сразу работать в single wire half-duplex: Rx/Tx MAX3485 соединить вместе и подать на Tx микроконтроллера. Правда, пришлось бы выпаивать MAX485 и впаивать вместо него MAX3485, чтобы избавиться от "мусора". Вот такие пироги с казалось бы простейшим интерфейсом! А ведь еще надо будет добавить обработку адреса устройства… Думаю, протокол будет таким же текстовым, как и по USB, но перед командой нужно будет писать число — адрес, выставляемый на плате переключателями (на фото он трехразрядный, хотя должен быть четырех — но мне с али еще новые dip-switches не пришли). Этот же адрес будет задавать идентификатор устройства на CAN-шине. Как закончу с обработкой адреса по RS-485, перейду к CAN'у. Для его отладки у меня есть старая девборда, которую надо будет по-быстрому переделать в USB<>CAN адаптер (а заодно и протокол придумать, по которому можно будет пакеты отправлять/принимать). Уже, кстати, давненько подумываю о том, что нужно на МК сделать какой-то "эмулятор баша" для отладки: чтобы при ручном вводе команд можно было стрелочками по истории гулять + табом автодополнение делать. По идее, оперативки у средних STM'ок столько, что они запросто эту хотелку должны потянуть! Справа внизу на фото — переходник на основе PL2303 для работы с RS-485, который я брал когда-то на али. На 115200 бод и коротком шнурке вполне нормально справляется, с бóльшими скоростями как-то работать не планирую.