
Мелкие вопросы по МК и ПЛИС.
- Сообщения: 3832
- Зарегистрирован: Сб сен 10, 2011 17:46:25
- Реклама
Разъясните кто-нибудь порядок настройки PLL в STM32F10x? Что за чем следует? Найденные куски кода либо не включают HSE (регистр настраивается именно для работы с HSE, по факту работает HSI, либо не пееключается), либо не включают умножитель.
HSI->PLL:
HSE->PLL:
Спойлер
Код: Выделить всё
RCC->CFGR |= RCC_CFGR_PLLMULL6; //HSI / 2 * 6 = 24 MHz
RCC->CR |= RCC_CR_PLLON; //enable PLL
while((RCC->CR & RCC_CR_PLLRDY) == 0) {} //wait till PLL is ready
RCC->CFGR &= ~RCC_CFGR_SW; //clear SW bits
RCC->CFGR |= RCC_CFGR_SW_PLL; //select PLL as system clock
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_1) {} //wait till PLL is used
Спойлер
Код: Выделить всё
RCC->CR |= RCC_CR_HSEON; //enable HSE
while((RCC->CR & RCC_CR_HSERDY) == 0) {} //wait till HSE is ready
RCC->CFGR |= RCC_CFGR_HPRE_DIV1 | //HCLK = SYSCLK
RCC_CFGR_PPRE2_DIV1 | //PCLK2 = HCLK
RCC_CFGR_PPRE1_DIV1; //PCLK1 = HCLK
RCC->CFGR &= ~RCC_CFGR_PLLMULL; //clear PLLMULL bits
RCC->CFGR |= RCC_CFGR_PLLSRC_PREDIV1 | //PLL source = PREDIV1
RCC_CFGR_PLLXTPRE_PREDIV1_Div2 | //HSE / 2 = 4 MHz
RCC_CFGR_PLLMULL6; //4 * 6 = 24 MHz
RCC->CR |= RCC_CR_PLLON; //enable PLL
while((RCC->CR & RCC_CR_PLLRDY) == 0) {} //wait till PLL is ready
RCC->CFGR &= ~RCC_CFGR_SW; //clear SW bits
RCC->CFGR |= RCC_CFGR_SW_PLL; //select PLL as system clock
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_1) {} //wait till PLL is used
Пользуюсь вот этим:
RCC_CFGR_SW_HSE - в этом случае работает PLL.
В случае записи вида:
RCC_CFGR_SW_PLL - в этом нет, работает только HSE.
Подмена вместо них RCC_CFGR_SW_0 или 1, на замену HSE и PLL так же результата не принесли.
Пользуюсь ЕмБлохом по причине слабого компа на работе. Хотя в данном случае это не имеет значения - CMSIS и SPL те же самые.
Спойлер
Код: Выделить всё
void Init_Clk()
{
FLASH->ACR |= FLASH_ACR_PRFTBE; //Включить буфер предварительной выборки
FLASH->ACR &= ~FLASH_ACR_LATENCY; //Очистить FLASH_ACR_LATENCY
FLASH->ACR |= FLASH_ACR_LATENCY_2; //Пропускать 2 такта
RCC->CFGR = 0;
[b] RCC->CFGR |= RCC_CFGR_SW_HSE; // Включаем SYSCLK от PLL ???
while ((RCC->CFGR & RCC_CFGR_SWS_HSE) == 1){}[/b]
RCC->CR &=~(RCC_CR_PLLON); // Отключаем PLL
while((RCC->CR & RCC_CR_PLLRDY) == 1){}
RCC->CFGR &=~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL); // Обнуление CFGR
RCC->CFGR |= RCC_CFGR_PLLSRC;
RCC->CFGR |= RCC_CFGR_PLLMULL16; // Умножить частоту PLL_MUL
RCC->CR |= RCC_CR_PLLON; // Запустить PLL
while((RCC->CR &RCC_CR_PLLRDY)==0){} // Ожидание готовности PLL
RCC->CFGR &= ~(RCC_CFGR_SW); // Очистить биты SW0 и SW1
RCC->CFGR |= RCC_CFGR_SW_PLL; // Тактирование с выхода PLL
while((RCC->CFGR & RCC_CFGR_SWS)!=0x08){} // Ожидание переключения на PLL
}В случае записи вида:
RCC_CFGR_SW_PLL - в этом нет, работает только HSE.
Подмена вместо них RCC_CFGR_SW_0 или 1, на замену HSE и PLL так же результата не принесли.
Пользуюсь ЕмБлохом по причине слабого компа на работе. Хотя в данном случае это не имеет значения - CMSIS и SPL те же самые.
- Сообщения: 145
- Зарегистрирован: Ср фев 01, 2012 10:55:53
Похоже что выражение
никогда не будет равно единице, так как
Лучше сравнивать с нулем.
Код: Выделить всё
(RCC->CFGR & RCC_CFGR_SWS_HSE) == 1Код: Выделить всё
#define RCC_CFGR_SWS_HSE ((uint32_t)0x00000004) /*!< HSE oscillator used as system clock */- Реклама
- Сообщения: 7
- Зарегистрирован: Ср окт 01, 2014 20:09:22
Какой програматор выбрать ?AVR
USB910 или USB bar Простите за тупой вопрос но определиться между ними не могу ! Буду рад Любой информацией !
Сюда перенес.
aen
USB910 или USB bar Простите за тупой вопрос но определиться между ними не могу ! Буду рад Любой информацией !
Сюда перенес.
aen
Надо во время отладки посмотреть ОЗУ в Keil-е.
Пробовал меню View->Memory windows->Memory1, далее вводил стартовый адрес 0. В окне отображается содержимое ПЗУ. А ОЗУ как посмотреть?
Пробовал меню View->Memory windows->Memory1, далее вводил стартовый адрес 0. В окне отображается содержимое ПЗУ. А ОЗУ как посмотреть?
Последний раз редактировалось paskal Вт фев 17, 2015 21:18:03, всего редактировалось 1 раз.
Если бы на станции "Мир" стояли Винды, она бы еще висела и висела...
Это что-то инопланетное ? Про программатор с таким именем не слышал. Если комп достаточно не новый и имеет LPT или COM, то для начинающего лучше "5 проводков" или AVR910 . А лучше купить у кетайцев на Ali USB ASP .дмитрий95 писал(а):Какой програматор выбрать ?AVR
USB bar
В окошке Address: пишем "i:0000" и смотрим.paskal писал(а):...А ОЗУ как посмотреть?
Соответственно "x" - это внешнее ОЗУ, а "c" - ПЗУ.
И все таки, подскажите кто знает можно ли проверить не нарушен ли функционал МК, потому что титька2313 читается и пишется успешно, но в рабочей плате никак не работает... Пробовал запрограммировать в том числе и на внутреннее тактирование (заводские настройки).
Написать тестовую программу, которая проверяет железо платы.
PS. Аватара о чём-то намекает?
PS. Аватара о чём-то намекает?
Docendo discimus
имхо, тема http://radiokot.ru/forum/viewtopic.php?f=57&t=113571 закрыта преждевременно, хотя в целом тема не новая. речь идет (вангую!) о ситуации, когда, например, выводы сегментов индикатора подключаются не к одному порту, а к разным, да еще и биты не по порядку, а вперемешку. думаю, каждый, кто сталкивался с трассировкой плат с семисегментниками сталкивался с этой проблемой: либо простая программа, выводящая сегменты в один порт, либо удобная разводка платы, оптимально подводящая пины индикатора к пинам МК.
когда я делал свои проекты из ряда "меньше не бывает", эта проблема была очень актуальной, и до сих пор приводит в ступор всех, кто пробует перебросить выводы иначе, чем сделал я.
к сожалению, однозначной методики решения подобной проблемы нет, если не считать промелькнувшей пару лет назад темы одного весьма уважаемого среди микроконтроллерщиков разработчика (вот убей меня бог, проклятый склероз не дает мне вспомнить, кто это был). только тема та была связана с шаблонами С++ и требовала просто колоссальных знаний языка С++, лично я не врубился, хотя круть ощутил...
обычно же перестановка битов сводится к следующему.
1. исходные данные
допустим, на входе имеем индикатор, у которого сегменты на выводы подаются в таком порядке ABCHGEFD
при этом удобнее всего развести сегменты ABCD на порт D микроконтроллера, причем в таком порядке побитово ...AB.DC, а остальные на порт С, причем в таком порядке E.F...HG
2. задача: написать код, поддерживающий "прозрачный" с точки зрения программиста вывод чисел на сегменты.
3. решение (в частном случае)
нарисуем табличку "соответствия" битов
хорошо видно, что для вывода в порт D надо биты AB сдвинуть вправо на 3 позиции, D на 1 влево, а C - на 5.
аналогично для вывода в порт С нужно E сдвинуть на 5 влево, F на 4 влево, а пару HG вправо на 3.
естественно, все прочие биты игнорировать, т.е. не менять.
лично я уже на этом этапе думаю: а на самом ли деле именно такое распределение сегментов по битам портов наиболее оптимально? и, если готов чем-то пожертвовать, я корректирую схему, а следовательно и распределение битов, т.е. перестраиваю таблицу соответствий. цель при этом - добиться наименьшего количества сдвигов. т.е. я стремлюсь разбросать сегменты так, чтобы как можно больше сегментов находились рядом друг с другом, чтобы двигать их все одновременно, как в случае с битами AB и HG - если бы тут было не по 2 сегмента в группе, а по 3 или даже 4 - все было бы просто идеально!
но продолжим рассмотрение нашего неудачного случая.
итак, мы определили, какие биты в какую сторону надо двигать, при этом знаем, что перед началом сдвигов надо отфильтровать их от остальных. т.е. наши действия сводятся к выделению нужных битов, сдвигов их и накоплении результата, который затем выводится в порт.
получается нечто такое:
надеюсь, понятно, что операция & служит для выделения значения определенного бита или группы битов, операция | для формирования самой группы битов, а инверсия вкупе с & выполняет функцию сбрасывания указанной группы битов, т.е. их обнуление. если это непонятно - курите битовые операции
вот как-то так...
понятно ли начинающим? 
когда я делал свои проекты из ряда "меньше не бывает", эта проблема была очень актуальной, и до сих пор приводит в ступор всех, кто пробует перебросить выводы иначе, чем сделал я.
к сожалению, однозначной методики решения подобной проблемы нет, если не считать промелькнувшей пару лет назад темы одного весьма уважаемого среди микроконтроллерщиков разработчика (вот убей меня бог, проклятый склероз не дает мне вспомнить, кто это был). только тема та была связана с шаблонами С++ и требовала просто колоссальных знаний языка С++, лично я не врубился, хотя круть ощутил...
обычно же перестановка битов сводится к следующему.
1. исходные данные
допустим, на входе имеем индикатор, у которого сегменты на выводы подаются в таком порядке ABCHGEFD
при этом удобнее всего развести сегменты ABCD на порт D микроконтроллера, причем в таком порядке побитово ...AB.DC, а остальные на порт С, причем в таком порядке E.F...HG
2. задача: написать код, поддерживающий "прозрачный" с точки зрения программиста вывод чисел на сегменты.
3. решение (в частном случае)
нарисуем табличку "соответствия" битов
Код: Выделить всё
символ ABCHGEFD
PORTD ...AB.DC
PORTC E.F...HG
аналогично для вывода в порт С нужно E сдвинуть на 5 влево, F на 4 влево, а пару HG вправо на 3.
естественно, все прочие биты игнорировать, т.е. не менять.
лично я уже на этом этапе думаю: а на самом ли деле именно такое распределение сегментов по битам портов наиболее оптимально? и, если готов чем-то пожертвовать, я корректирую схему, а следовательно и распределение битов, т.е. перестраиваю таблицу соответствий. цель при этом - добиться наименьшего количества сдвигов. т.е. я стремлюсь разбросать сегменты так, чтобы как можно больше сегментов находились рядом друг с другом, чтобы двигать их все одновременно, как в случае с битами AB и HG - если бы тут было не по 2 сегмента в группе, а по 3 или даже 4 - все было бы просто идеально!
но продолжим рассмотрение нашего неудачного случая.
итак, мы определили, какие биты в какую сторону надо двигать, при этом знаем, что перед началом сдвигов надо отфильтровать их от остальных. т.е. наши действия сводятся к выделению нужных битов, сдвигов их и накоплении результата, который затем выводится в порт.
получается нечто такое:
Код: Выделить всё
// для удобства определим константы, определяющие биты сегментов
#define A 0x80
#define B 0x40
... и так далее
// в этой переменной у нас будет число, которое надо вывести на сегменты
char symbol;
// далее я разобью оператор на строки, чтобы было понятнее, в каком месте что делается
PORTD = // в порт D будет выводиться
(PORTD & ~(A | B | D | C)) // содержимое тех битов порта, которые не назначены сегментам, отсюда инверсия перед скобками
| (((symbol & (A | B)) >> 3) // сдвинутые на 3 позиции вправо биты AB
| ((symbol & D) << 1) // сдвинутый на 1 влево бит D
| ((symbol & C) << 5) // и сдвинутый на 5 влево бит С
; // все, наконец-то
// аналогично надо сформировать и новое значение порта С - не буду делать этого в целях экономии своих сил
вот как-то так...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Там у ТС'а проблема с использованием отдельных бит и масок. Он не знает как к этому подойти даже.
По этой теме полно информации во всемирной помойке, по этому тему и закрыл. А то там уже начался всякий флуд и троллизм, в виде восхваления конкретных языков программирования.
По этой теме полно информации во всемирной помойке, по этому тему и закрыл. А то там уже начался всякий флуд и троллизм, в виде восхваления конкретных языков программирования.
ну, поскольку этот форум тоже часть всемирной помойки, я и добавил маленькую кучку от себя 
в дополнение к написанному отмечу, что операции над портами в том виде, как написал в примере кода я, должны либо делаться атомарно, либо находиться внутри обработчика прерываний (что, кстати, чаще всего и бывает - динамическая индикация если). в общем, т.к. мой многострочный оператор будет выполняться довольно долго, надо предпринять меры, чтобы за это время не произошло прерывание и содержимое порта или переменной symbol не изменилось - это важно.
в дополнение к написанному отмечу, что операции над портами в том виде, как написал в примере кода я, должны либо делаться атомарно, либо находиться внутри обработчика прерываний (что, кстати, чаще всего и бывает - динамическая индикация если). в общем, т.к. мой многострочный оператор будет выполняться довольно долго, надо предпринять меры, чтобы за это время не произошло прерывание и содержимое порта или переменной symbol не изменилось - это важно.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Помнится, я тоже задавал вопрос по "виртуальному" порту, т.е. отдельные биты переносить на другой физический порт, при этом программно это долно выглядеть как будто я обращаюсь к одному некоему порту (виртуальному). Кажется кто то даже на него пытался ответить тогда.
В каждом семействе МК есть свое самое оптимальное решение проблемы...
Одначе во всех без исключения сработает побитовая развертка исходного байта в бит0(или бит7) восьми буферных регистров ОЗУ с последующей произвольной обратной сверткой согласно заданного шаблона.

Одначе во всех без исключения сработает побитовая развертка исходного байта в бит0(или бит7) восьми буферных регистров ОЗУ с последующей произвольной обратной сверткой согласно заданного шаблона.
А я бросил экономить тактики, и всегда в порты пишу по одному биту. Тогда не важно, где они расположены.
Доступ к битам порта оформлен в виде макросов, которые определены в файле main.h:
Для STM32 пишу на C++, там для обращения к пину порта использую шаблонный класс с перегруженными операторами, поэтому все выглядит еще проще:
Код: Выделить всё
void SetSeg(char s)
{
(s & _A_)? Port_SEG_A_0 : Port_SEG_A_1;
(s & _B_)? Port_SEG_B_0 : Port_SEG_B_1;
(s & _C_)? Port_SEG_C_0 : Port_SEG_C_1;
(s & _D_)? Port_SEG_D_0 : Port_SEG_D_1;
(s & _E_)? Port_SEG_E_0 : Port_SEG_E_1;
(s & _F_)? Port_SEG_F_0 : Port_SEG_F_1;
(s & _G_)? Port_SEG_G_0 : Port_SEG_G_1;
(s & _H_)? Port_SEG_H_0 : Port_SEG_H_1;
}
Код: Выделить всё
#define SEG_A (1 << PB6)
...
#define Port_SEG_A_0 (PORTB &= ~SEG_A)
#define Port_SEG_A_1 (PORTB |= SEG_A)
...
Код: Выделить всё
TGpio<PORTA, PIN1> Pin_SEG_A;
...
Pin_SEG_A.Init(OUT_PP_2M, OUT_LO);
...
Pin_SEG_A = (s & _A_);
...
Приветствую! По поводу программирования МК, подкинули мне такую штуку для прошивки ЭБУ рус тазов ПАК загрузчик v. 3 USB, возможно ли с помощью этой машинки шить МК типа PIC, Atmel,т.п., или же проще разорится на программатор?
- Вложения
-
- nnkrviyn.jpg
- (3.15 КБ) 243 скачивания
-
- pak.jpg
- (3.17 КБ) 354 скачивания
Зашёл на сайт ST и увидел, что они усердно похерили SPL. Необходим под F0, поясню - проект переписывать под HAL придётся, а так есть готовые исходнички без геморроя. Ни у кого не завалялся случайно?
Странно, я качал пакет для F072 дискавери, там есть полный STM32F0xx_StdPeriph_Driver.


