Pull to refresh

Comments 16

Применение прерывания INT0/INT1 сильно ограничивают положение вывода под приём…
Да и сама функция UART без внешнего тактового сигнала сомнительна. Внутренний генератор обладает очень низкой точностью и даже с калибровкой уплывает от температуры и напряжения питания. Только в TYNY45/85 есть температурная стабилизация встроенного генератора.
Как-то пробовал UART аппаратный но с внутренним генератором на ATMEGA48, точности не хватает. Даже после калибровки во время работы частота уходит и на другом конце начинают лезть ошибки приёма, и не на всех переходниках USB-UART есть возможность подбирать кастомную скорость передачи с необходимым шагом.
Да, действительно, я совершенно упустил из виду то, что INT0 жестко привязывает пин PB1 к использованию на вход. Исправлю на использование прерывания PCINT. Насчет нестабильности — лично я не проверял в температуре, но на моем тестовом образце я поставил значение OCR0A равным 0х70 — вроде бы все работает как положено, ошибок нет, осциллографом проверял длительность бита — все в порядке. Ну, а выбирать в общем-то и не приходится, статья то про ATtiny13, и если на ней необходимо сделать UART, то других вариантов нет.
PCINT не различает фронт/спад… там только одно понятие: изменение состояния.

ATTINY13 может тактироваться внешним сигналом.

По даташиту, зависимости частоты внутреннего генератора от напряжения и температуры просто жуткие. Скорей всего хорошо отрабатывает именно другая сторона подстраиваясь под скорость передачи вашего контроллера.

Погрешность скорости в 2% и последний бит уже находится не в своём фрейме, а подстройка внутреннего генератора если не ошибаюсь происходит шагами по 0.5-1% запас очень небольшой, и надо тщательно калибровать чтобы не выйти за пределы допустимого отклонения.
Сколько использовал внутренний RC генератор никогда с уартом не было проблем вплоть до 38400. Вы часом не на али контроллеры покупаете?
Может не повезло и калибровка оказалась как раз на грани сбоя. На 38400 иногда получал 0xFE вместо 0xFF, и это иногда было слишком частым — навскидку с вероятностью около 1/20. Устал с этим бороться и бросил эту затею.
Не всё измеряется деньгами простоту, например, ни за какие деньги не купишь.
Более того, есть еще ATTINY10 в SOT-23 корпусе, вообще 6-ногий товарищ.

Цена начинает играть роль только при крупносерийном производстве а в остальном — доступность и качество документации.

Под STM32 нужно еще учится, искать документацию, разобраться в бардаке множества сред разработки — чтобы разобраться в STM-ках нужна очень сильная мотивация и направляющий импульс.
Просто потому что 8-ногий DIP значительно проще использовать чем 20-ногий TSSOP или еще хуже LQFP. Да и глупо как-то выглядит использование STM32 для принятия по UART пары байт и управления нагревательным элементом. (Для этого я использовал эту ATtiny — нагрев и датчик температуры с передачей данных по UART)
Посмотрите ATtiny441/841. Два настоящих UART, термостабилизация внутреннего генератора и всего 14 ног, правда в SOIC-корпусе. Эволюция ATtiny 24/44/84.
Стоимость? оно то конечно не так важно, но обидно использовать дорогой контроллер и сознательно не пользоваться избыточной периферией когда это можно сделать на более дешёвом.
Если не в ущерб качеству, то конечно.

Просто если в дешевом частота внутреннего генератора уплывает, а кварц или внешнее тактирование делать не хочется, или еще какие ограничения выявляются, то вот можно взять ATTiny441 с аппаратным уартом (даже с двумя).
В одном магазине посмотрел — в 2 раза дороже стоят чем ATTiny44.
UART конечно хорошо, но в таких случаях ИМХО имеет смысл использовать SPI не зависящий от тактовой частоты.
Если передачу оборвать, то вот здесь:
int16_t uart_recieve(uint8_t* rb)
...
while(rxbitcount);
...

мы и останемся, навсегда.
Может лучше, что бы функция приема возвращала байт если он принят или ничего если нет?
Был не прав, поторопился с выводами, rxbitcount обнулится таймером.

Мне не нравится, что uart_recieve() вынуждает задерживаться в ней если начат прием байта. Лучше иметь буфер хотя бы на один уже принятый байт, а принимаемый собирать отдельно (вроде в аппаратном UARTе так и сделано).

И еще, если не «повезет»:
int16_t uart_recieve(uint8_t* rb)
{
	if(rxbitcount < 0x09)		// Если счетчик бит на прием меньше 9
	{
		while(rxbitcount);	// Ждем пока завершится текущий прием
// !!!!!!!!!!!!!!!!!!!!!
// если в этот момент случится прерывание INT0, то в rxbyte обнулится
// !!!!!!!!!!!!!!!!!!!!!
		*rb = rxbyte;		// Пишем по адресу указателя принятый байт
		rxbitcount = 0x09;	// Восстанавливаем значение счетчика бит
		return (*rb);		// Возвращаемся
	}
	else
	{
		return (-1);		// Иначе возвращаем -1 (принимать нечего)
	}
}

можно получить ноль вместо реально переданного байта
Ну, я сознательно не стал добавлять буфер, это увеличило бы объем кода.
По поводу «повезет» — это вряд ли, если rxbitcount стала нулем, значит мы только что получили стоповый бит и у нас уж точно есть время, чтобы выполнить одну операцию.
Sign up to leave a comment.

Articles