eddy писал(а): ↑01.12.2009 09:14
Собственно вопрос: как можно установить произвольную скорость? Работаю с микроконтроллером по RS-232, из стандартных скоростей у него только ~9600 и ~19200 бод, остальные =250кбод/N, где N - целое. Скорости передачи данных не хватает (нужно успеть передать четыре считанных по SPI-интерфейсу байта за паузу между передачами, ~100мкс). Т.е. здесь очень подошла бы скорость 83.3кбод и выше (хотелось бы даже 250кбод).
В интернете нашел только такой вариант:
Код: Выделить всё
struct serial_struct nuts, old_extra_term; int RB;
ioctl(comfd, TIOCGSERIAL, &old_extra_term);
nuts = old_extra_term;
nuts.baud_base = Baudrate; // вариант 1
nuts.custom_divisor = 1; // вариант 1
// вариант 2:
// nuts.custom_divisor = nuts.baud_base / Baudrate;
//if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
nuts.flags &= ~ASYNC_SPD_MASK;
nuts.flags |= ASYNC_SPD_CUST;
ioctl(comfd, TIOCSSERIAL, &nuts);
ioctl(comfd, TIOCGSERIAL, &nuts);
RB = nuts.baud_base / nuts.custom_divisor;
printf("Target baudrate=%d, real baudrate=%d\n", Baudrate, RB);
Работает только при установке SUID-бита или запуске от рута. printf пишет, что скорость установилась нужная (правда, во втором варианте nuts.baud_base = 115200), однако, данные через канал не идут.
Ошибка точно не со стороны контроллера, т.к. если выставляю таким способом стандартную скорость 9600бод, компьютер контроллер не видит.
Может быть, кто-нибудь сталкивался с такой проблемой?
baud_base устанавливается осью и зависит от параметров микросхемы UART. Стандартный UART 16550A тактируется от кварца
1843200 Гц, 1843200/16=115200, что соответствует обычно максимальной скорость обмена. 16550 устроена так, что частоту кварца она делит на 16. Так что играть можно только при помощи custom_divisor.
eddy писал(а): ↑01.12.2009 09:14
P.S. Кажется мне, в офтопике можно было задавать произвольный бодрейт, так что проблема не аппаратная.
Не совсем так. baud_base маздай менять тоже не может. Тут ведь вся соль в чём: драйвер должен посчитать этот дивизор (делитель) и записать его в регистры микросхемы 16550A, аналогично тому, что Вы делаете для МК. Например, для Atmel AVR это регистры UBRR [H,L]. Здесь такая же пестня. Чтобы получить скорость 115200, надо записать делитель 1, 57600 - 2, etc. Просто в маздае скорость задаётся по-другому: каждый раз она делает 115200/bps=custom_divisor и т.д.
Для того, чтобы менять скорость так точно, нужна другая микросхема UART. Есть микросхемы с более высокими частотами тактирования, хз как называются.
Вывод: "Используй то, что под рукою, и не ищи себе другое!" © :-(
Я, например, взял себе привычку программировать контроллеры
только на стандартные скорости обмена. Не надо искушать судьбу и искать геморроя на свою задницу. Если не хватает скорости обмена, то надо искать другой интерфейс, подумать о USB, CAN и т.д.