[/uquote]Это за гранью добра и зла. Вы все эти параметры в голове держите или по 10 раз в описание класса лазите, чтобы его инициализировать не ошибившись? Как тут можно не перепутать куда какой пин пихать? А уж 50,14,1 это вообще магия.
[uquote="a5021",url="/forum/viewtopic.php?p=3386864#p3386864"]Это нечитабельно. Как наглядно инициализировать AFR я уже показывал. Теперь MODER:[/uquote]
У меня полная конфигурация GPIO чипа F427ZI, а это 7 портов (7*16 = 112 ног) занимает около 60 строк. На одном экране я могу задать/проверить полную конфигурацию любой ноги не рыская по коду.
[uquote="VladislavS",url="/forum/viewtopic.php?p=3386934#p3386934"]Это за гранью добра и зла. Вы все эти параметры в голове держите или по 10 раз в описание класса лазите, чтобы его инициализировать не ошибившись? Как тут можно не перепутать куда какой пин пихать? А уж 50,14,1 это вообще магия.[/uquote]
Последние 3 цифры - это тайминги, при их подборе можно и не знать какой именно за что отвечает, т.к. требуемые значения для различных экранов тоже могут составлять великую тайну, потому подбор часто выполняется на глаз, с запасом. А 50 - это я что-то тестил, число должно быть намного меньше В описание класса лазить не нужно, по мере набора этой строки IDE выдает подсказки, я лишь ввожу нужные пины, а потом мне без надобности знать какой пин за что отвечает, т.к. класс изначально был отлажен и работает, а внутрь класса все пины попадает с осмысленными именами. Какую-то полезную информация представляет разве что знание о том, какие в целом пины там задействованы и это я прекрасно вижу. Сам же говорил, берется схема и по ней инициализируются порты, только я когда вижу в схеме, что LCD_CS - это PA2, то передаю в шаблон PinA<2>, а у тебя придется устанавливать биты в регистрах и во время инициализации, и во время дальнейшего использования. Опять же, если сильно хочется, то можно поназначать псевдонимы всем пинам, но мне, как автору, это не видится как нечто обязательное.
Вам что-нибудь известно о хорошем тоне в программировании ? Или, как автору, вам это не видится обязательным?
Одному 60 строк голых цифр удобно и информативно, другому волшебные числа заменили все. ЧуднЫе события здесь происходят.
Не важно сколько экранов будет занимать инициализация GPIO. Важно, чтобы оно одинаково легко (понятно) читалось и через день и через год, а форма записи максимально препятствовала использованию ошибочных значений.
Если вам для инициализации одного регистра надо целый экран кода, а для порта в 7 регистров - 7 экранов, то вы их неизбежно будете копипастить. Глаз замылится на таком количестве текста и вы будете неизбежно допускать вот такие дурацкие ошибки, как несколько часов назад на другом форуме встретил
Много осмысленного текста, а ошибку не вчитываясь хрен заметишь, особенно если это многостраничные портянки. Делаешь один раз заготовку под используемый проц и расставляй себе единички/нолики.
Главное чтобы в пределах экрана была подсказка что это значит. При таком подходе я не копипащу тонны "осмысленного текста", а расставляю нужные значения на свои места.
Можно, конечно, всё строго типизировать, но это большая и муторная работа, которую делать за производителя чипов не хочется.
[uquote="a5021",url="/forum/viewtopic.php?p=3386977#p3386977"]Одному 60 строк голых цифр удобно и информативно, другому волшебные числа заменили все. ЧуднЫе события здесь происходят.[/uquote]
Честное слово, ведешь себя как какой-то гуманитарий Магические числа, а не никакие ни волшебные, даже гугл по "волшебным" числам ставит на первые два места какой-то женский сайт, где желающим похудеть рекомендуют представить себя стройной и повторять: "десять минус один"
Можно, конечно, всё строго типизировать, но это большая и муторная работа, которую делать за производителя чипов не хочется.
Строго типизировать можно и нужно, но в С это нормально не сделаешь. И еще интересно, у тебя такой шаблон где единички можно расставлять под каждый мк есть? У F407, например, периферию можно включать для AHB1/AHB2/AHB3/APB1/APB2 и еще столько же для их LP версий, которые полностью не совпадают. А F429 добавляет еще дополнительную периферию, означает ли это, что нужно где-то хранить по 10 наборов на каждый из этих двух мк?
Последний раз редактировалось Reflector Вс май 27, 2018 20:56:21, всего редактировалось 1 раз.
[uquote="Reflector",url="/forum/viewtopic.php?p=3387033#p3387033"]И еще интересно, у тебя такой шаблон где единички можно расставлять под каждый мк есть?[/uquote] Под те процы, с которыми я работаю - да. F427ZI
Спойлер
IDE выдает список, выбираешь что нужно. При смешении разной периферии естественно будет ошибка компиляции. Понять какая именно периферия включена значительно легче когда видишь только ее, но все перечисления пришлось объявлять самому.
[uquote="Reflector",url="/forum/viewtopic.php?p=3387059#p3387059"]но все перечисления пришлось объявлять самому.[/uquote]Алаверды. Под все процы? Это же нужно где-то хранить!
А ещё я стараюсь не переобзывать регистры/биты. Потому что когда работаешь с даташитом, хидером, форумом в конце концов, то поиском проще пользоваться когда везде одинаковое название. Бывает, правда, когда в хидере встречаются несоответствия с даташитом, то правлю хидер. И тоже где-то его храню...
[uquote="VladislavS",url="/forum/viewtopic.php?p=3387071#p3387071"]Алаверды. Под все процы? Это же нужно где-то хранить! [/uquote]
А Hse::enable() где, по-твоему, хранится? Там же находятся и все перечисления имеющие отношение к модулю RCC.
А ещё я стараюсь не переобзывать регистры/биты. Потому что когда работаешь с даташитом, хидером, форумом в конце концов, то поиском проще пользоваться когда везде одинаковое название. Бывает, правда, когда в хидере встречаются несоответствия с даташитом, то правлю хидер. И тоже где-то его храню...
Я иногда переобзываю по одной просто причине, по имени не всегда понятно что данный бит означает.
ps. Хидер уж очень режет слух, транскрипция для head - [hed], нет там никакого "и"
[uquote="VladislavS",url="/forum/viewtopic.php?p=3387009#p3387009"]Если вам для инициализации одного регистра надо целый экран кода, а для порта в 7 регистров - 7 экранов, то вы их неизбежно будете копипастить.[/uquote]
Зачем же такую примитвную чепуху из пальца высасывать? Копипастить там особо не получится, т.к. пины разные и назначения у них разное. Придется либо со схемы, либо с какой-то таблички переносить информацию практически попиново. Кроме того, каждая строка это один пин, где сначала идет его номер, а потом режим:
Теперь тест на сообразительность: удобнее конфигурацию пину прописывать в строке, где его номер значится или каждый раз считать, какая это цифра с края или по порядку?
Здравствуйте. Набыдлокодил небольшой примерчик уарт на stm32f103c8t6. Вобщем работает уарт, эхо отстукивает, единственная проблема непонятная кодировка в консоле. Какие могут быть решения. Пните в нужном направлении. Спойлер
#include "stm32f10x.h"
#define LED_BLUE 7 /* PB7 is the blue LED */
#define LED_GREEN 6 /* PB6 is the green LED */
#define MODE_ON 0 /* Offset to add to pin for ON */
#define MODE_OFF 16 /* Offset to add to pin for OFF */
void board_init(void)
{
// Most of the peripherals are connected to APB2. Turn on the
// clocks for the interesting peripherals
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPBEN;
// USART2 Settings
// SET TX2
GPIOA->CRL &= ~GPIO_CRL_CNF2;
GPIOA->CRL |= GPIO_CRL_CNF2_1;
GPIOA->CRL |= GPIO_CRL_MODE2_0;
// SET RX2
GPIOA->CRL &= ~GPIO_CRL_CNF3;
GPIOA->CRL |= GPIO_CRL_CNF3_0;
GPIOA->CRL &= ~GPIO_CRL_MODE3;
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
// Configure BRR by deviding the bus clock with the baud rate for 19200 on 36Mhz
USART2->BRR = 0x753;
// Enable the USART, TX, and RX circuit
USART2->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE;;
// Put PB7 and PB6 into output mode (the build blue and green LEDs)
GPIOB->CRL &= ~(GPIO_CRL_MODE6 | GPIO_CRL_CNF6);
GPIOB->CRL |= GPIO_CRL_MODE6;
GPIOB->CRL &= ~(GPIO_CRL_MODE7 | GPIO_CRL_CNF7);
GPIOB->CRL |= GPIO_CRL_MODE7;
// NVIC_EnableIRQ (USART2_IRQn);
//
// __enable_irq ();
}
void delay(int cnt)
{
while (cnt-- > 0)
{
__asm("nop");
}
}
int usart_rec(void)
{
/* Wait until the data is ready to be received. */
while ((USART2->SR & USART_SR_RXNE) == 0);
// read RX data, combine with DR mask (we only accept a max of 9 Bits)
return USART2->DR & 0x1FF;
}
void usart_snd(int data)
{
USART2->DR = data;
// wait for TX
while ((USART2->SR & USART_SR_TXE) == 0);
}
void usart_snd_str(char *str)
{
int i = 0;
while(str[i] != 0)
{
usart_snd(str[i++]);
}
}
void set_led(int led, int mode)
{
GPIOB->BSRR = 1<<(led + mode);
}
void flash_led(int led)
{
set_led(led, MODE_ON);
delay(15000);
set_led(led, MODE_OFF);
}
int main(void)
{
board_init();
usart_snd_str("\n\rHello, please type something\n\r");
for(;;) {
// read blocking form usart
int rec = usart_rec();
// flash green led to indicate we received data
flash_led(LED_GREEN);
if(rec == '\r') {
usart_snd_str("\n\r");
} else {
// send data blocking to usart
usart_snd('[');
usart_snd(rec);
usart_snd(']');
}
// flash blue led to indicate we send data
flash_led(LED_BLUE);
}
}
Если считать из учёта PCLK1=36 МГц, то магическое число 0x753 посчитано правильно. А вот как 36 МГц получены от нас спрятали или вообще забыли? И ещё, BRR менять можно только при выключенном порту. Проц при старте точно сброщен?
Так то код корявенький, но принципиальных ошибок, влияющих на передачу, не видно.
Так, по мелочам.
В DR и так будут 0 в незадействованных разрядах.
[/uquote]
В данном случае не принципиально, т.к. передача и возврат параметров производятся через регистры, а они 32-битные. Что для восьмибитного возвращаемого значения будет использован один РОН целиком, что для 32-битного.
Дальше по коду компилятор будет приводить эти знаковые 32 бита к 8, а это не всегда "бесплатно". Применение типов не соответствующих данным - источник потенциальных ошибок. Лучше приучиться применять правильные типы всегда.
[uquote="VladislavS",url="/forum/viewtopic.php?p=3389564#p3389564"]Дальше по коду компилятор будет приводить эти знаковые 32 бита к 8, а это не всегда "бесплатно".[/uquote]
Ничего он приводить в данном случае не будет. Не нужно нагонять жути. Смотрите код -- функция возвращает значение типа int, которое присваивается переменной с тем же самым типом. Приличия, таким образом, соблюдены.
Вообще же, в классическом Си большая часть встроенных функций возвращает тип int и никто не убивается по поводу, что "применяется тип не соответствующий данным".