Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: отладка в Keil
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
mihlit
Код
GPIOD->BSRR |= GPIO_BSRR_BS2;            //Request -> 1
    Delay(1);
    GPIOD->BSRR |= GPIO_BSRR_BR2;            //Request -> 0
    
    while(!(GPIOD->IDR & GPIO_IDR_IDR3)) {}    //ждать Ready
    
        for(i=0; i<16; i++)
        {
            GPIOD->BSRR |= GPIO_BSRR_BS6;            //Read -> 1
            buf[i] = GPIO_ReadInputData(GPIOC);
            GPIOD->BSRR |= GPIO_BSRR_BR6;            //Read -> 0
        }
        
    while(1)
    {
        
    }

Когда программа запускается по сбросу, лог. анализатор показывает обмен сигналами между МК и внешним устройством.
Если я запускаю программу в отладчике, на строчке

while(!(GPIOD->IDR & GPIO_IDR_IDR3)) {} //ждать Ready
отладчик зависает. Объясните начинающему (стаж 4,5 мес), почему так происходит?
Obam
IDR, который для GPIOD, часом не мониторится в окошке Keil-а? Если так, то отладчик флажок вычитывает.
Обычно, флажки, сбрасываемые чтением, в окошках отладчика смотреть не полезно (при отладке wink.gif ).

"Зависает" и "не идет дальше" - не одно и то же.
Arlleex
Цитата(Obam @ Aug 18 2018, 17:19) *
IDR, который для GPIOD, часом не мониторится в окошке Keil-а? Если так, то отладчик флажок вычитывает.

Это не бит с доступом типа "сброс при чтении".

mihlit, когда заходите в отладку, процессор прошивается актуальной прошивкой, запускает ее выполнение, успевает сколько-то выполниться и затем отладчик сбрасывает его, начиная выполнять код заново. Поэтому с большой долей вероятности обмен Ваш уже завершился с устройством и повторный обмен не предусмотрен - поэтому лог. 1 на линии больше никогда не будет.
x893
В IDR при чтении нисего не сбрасывается.
Для GPIOD->BSRR не надо |=, просто =
mihlit
"Поэтому с большой долей вероятности обмен Ваш уже завершился с устройством и повторный обмен не предусмотрен - поэтому лог. 1 на линии больше никогда не будет."
Действительно, сейчас внешнее устройство снимает сигал готовности, после передачи пакета данных.
Получается, что я в режиме отладки не могу посмотреть данные в buf[]?

Кнопки пошагового выполнения становятся неактивными - это "Зависает" или "не идет дальше"?
Arlleex
Цитата(mihlit @ Aug 19 2018, 04:48) *
Действительно, сейчас внешнее устройство снимает сигал готовности, после передачи пакета данных.
Получается, что я в режиме отладки не могу посмотреть данные в buf[]?

Можете. Для этого Вам необходимо пересмотреть протокол передачи данных. Ну или на крайний случай, сделайте временный костыль: в начале main() сделайте задержку секунды в 3.
Кстати. Галочка в настройках отладчика Download To Flash->Reset and Run не стоит? Сбросьте ее.

Цитата(mihlit @ Aug 19 2018, 04:48) *
Кнопки пошагового выполнения становятся неактивными - это "Зависает" или "не идет дальше"?

Они в любом случае будут недоступны, если процессор находится в состоянии выполнения команд. Стоит Вам поставить точку останова на Ваш "зацикленный" круг ада - и Вы увидите, что кнопки разблокируются.
mihlit
Цитата
Можете. Для этого Вам необходимо пересмотреть протокол передачи данных.

Я примерно это и предполагал - поэтому и уже снова открыл Quartus.
Цитата
Галочка в настройках отладчика Download To Flash->Reset and Run

не очень разбираюсь в Кейле, искал в свойствах проекта, (волшебная палочка biggrin.gif ) не нашел.
Arlleex
Цитата(mihlit @ Aug 19 2018, 13:06) *
Я примерно это и предполагал - поэтому и уже снова открыл Quartus.

не очень разбираюсь в Кейле, искал в свойствах проекта, (волшебная палочка biggrin.gif ) не нашел.

Flash->Configure Flash Tools->Debug->Settings->Flash Download->Reset and Run.
mihlit
Дважды смотрел вкладку, но искал установленные птички - поэтому и не увидел. Сброшена она.
Ладно, спасибо всем, буду переделывать прошивку CPLD. Смущает только одно - всегда МК был мастером для периферии, а теперь что, по прерыванию обрабатывать прием данных, а если они сейчас не нужны? Ладно, разберусь.
Еще раз всем спасибо.
mihlit
Чтобы не плодить тем, спрошу здесь, кто-нибудь подскажите:
Есть в GPIO регистр GPIOx_AFRH.
Как в нем установить AFRH15[3:0] =5?
Записать магическое число 0х50000000 или есть какой-то дефайн? Смотрел stm32f4xx.h, stm32f4_gpio.h - не нашел. Ткните-пните в нужном направлениию
Arlleex
Цитата(mihlit @ Sep 1 2018, 14:07) *
Чтобы не плодить тем, спрошу здесь, кто-нибудь подскажите:
Есть в GPIO регистр GPIOx_AFRH.
Как в нем установить AFRH15[3:0] =5?
Записать магическое число 0х50000000 или есть какой-то дефайн? Смотрел stm32f4xx.h, stm32f4_gpio.h - не нашел. Ткните-пните в нужном направлениию

В stm32f4xx_gpio.h есть
Код
#define GPIO_AF_SPI1          ((uint8_t)0x05)  /* SPI1 Alternate Function mapping      */
#define GPIO_AF_SPI2          ((uint8_t)0x05)  /* SPI2/I2S2 Alternate Function mapping */
#define GPIO_AF_SPI4          ((uint8_t)0x05)  /* SPI4 Alternate Function mapping      */
#define GPIO_AF_SPI5          ((uint8_t)0x05)  /* SPI5 Alternate Function mapping      */
#define GPIO_AF_SPI6          ((uint8_t)0x05)  /* SPI6 Alternate Function mapping      */

А в В stm32f4xx_gpio.c есть
Код
void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)
{
  uint32_t temp = 0x00;
  uint32_t temp_2 = 0x00;
  
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
  assert_param(IS_GPIO_AF(GPIO_AF));
  
  temp = ((uint32_t)(GPIO_AF) << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4));
  GPIOx->AFR[GPIO_PinSource >> 0x03] &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4));
  temp_2 = GPIOx->AFR[GPIO_PinSource >> 0x03] | temp;
  GPIOx->AFR[GPIO_PinSource >> 0x03] = temp_2;
}

По сути делает то, что Вам нужно.

Если не используете SPL, то что мешает вовсе использовать самописные #define?
mihlit
Смотрел я GPIO_PinAFConfig, но по своей неопытности предположил, что как-то по аналогии со 103 серией, без приведения к uint32_t и сдвигов можно обойтись.
Спасибо за ответ, у меня код рабочий с SPL написан, но в целях самообразования попытался обойтись записью в регистры - не получилось.
Arlleex
Цитата(mihlit @ Sep 1 2018, 15:20) *
Смотрел я GPIO_PinAFConfig, но по своей неопытности предположил, что как-то по аналогии со 103 серией, без приведения к uint32_t и сдвигов можно обойтись.
Спасибо за ответ, у меня код рабочий с SPL написан, но в целях самообразования попытался обойтись записью в регистры - не получилось.

А что конкретно не получилось?
Записать в AFRH15[3:0] число 5 можно, например, так
Код
GPIOA->AFRH = 5UL << 28;

или так
Код
GPIOA->AFRH = 0x50000000;

что абсолютно равнозначно. Разница в удобстве записи и восприятия.
mihlit
Код
GPIOA->AFRH = 0x50000000;

Ассистент после -> предлагал только "AFR", если я вводил "AFRH", появлялся крест на строке "не объявлено uint32_t"
Professor Chaos
Цитата(mihlit @ Sep 1 2018, 13:07) *
Записать магическое число 0х50000000 или есть какой-то дефайн? Смотрел stm32f4xx.h, stm32f4_gpio.h - не нашел. Ткните-пните в нужном направлениию

Любое битовое поле в регистре в общем случае записывается в два прохода:
сначала выставляются 1 в нужных позициях
затем 0
Можно наоборот, порядок не важен.
Для этого нужно знать: имя модифицируемого регистра, позицию битового поля внутри регистра, маску этого битового поля и нужное значение.
Оформить эти 2 строчки кода можно в виде макроса
Код
// Макрос записи в регистр reg битовой последовательности val в позицию pos (по младшему разряду)
// msk - маска битового поля
#define TuneBitField(reg,val,pos,msk) \
                {(reg) |= (((val) << (pos))&(msk)); \
                (reg) &= (((val) << (pos))|~(msk));}

Имена регистров ( в вашем случае это GPIOA->AFRH), позиции и маски битовых полей описываются в .h-файле на конкретный микроконтроллер. Берёте их оттуда и подставляете в качестве аргументов макроса. В качестве значения val подставляете требуемое 5.
Сергей Борщ
QUOTE (Professor Chaos @ Sep 1 2018, 21:04) *
Любое битовое поле в регистре в общем случае записывается в два прохода:
сначала выставляются 1 в нужных позициях
затем 0
Можно наоборот, порядок не важен.
Кто вас научил такому ужасному ужасу, "библиотеки"? Что будет делать контроллер, получив 1 в нужных позициях и случайные предыдущие значения вместо нулей в остальных (или наоборот, не важно)? Я уже не говорю о лишней записи в регистр. Грамотный программист использует либо конструкцию Reg = (Reg & Mask1) | Mask2, либо ее же, разбитую на два выражения и временную переменную.
И еще - грамотный программист сложное выражение в #define обрамляет в do {} while(0)
mihlit
Объяснюсь по поводу своего вопроса.
1. На просторах Интернета много раз встречал высказывания, что "магическое" число - это не есть хорошо.
2. ИМХО, работа через регистры более компактна и нагляднее чем применение библиотек.
3. Из п2. вытекает(для меня), что написание своих макросов и дефайнов не сокращает время долбания клавиатуры и не повышает читаемость кода.
mihlit
Задам еще вопрос по Keil. У меня версия 5.23 (32Кб). Иногда при запуске Keil, теряется какой-то заголовочный файл. Лечится перезагрузкой Keil, но чаще приходится перезагружать Win7. Не смертельно, но иногда задалбывает. Кто- нибудь сталкивался с подобным?
Professor Chaos
Цитата(Сергей Борщ @ Sep 1 2018, 21:34) *
Что будет делать контроллер, получив 1 в нужных позициях и случайные предыдущие значения вместо нулей в остальных (или наоборот, не важно)? Я уже не говорю о лишней записи в регистр. Грамотный программист использует либо конструкцию Reg = (Reg & Mask1) | Mask2, либо ее же, разбитую на два выражения и временную переменную.

Согласен с замечанием.
Так лучше?
Код
// Макрос записи в регистр reg битовой последовательности val в позицию pos (по младшему разряду)
// msk - маска битового поля
#define TuneBitField(reg,val,pos,msk) \
                do { \
                    tmp=reg; \
                    (tmp) |= (((val) << (pos))&(msk)); \
                    (tmp) &= (((val) << (pos))|~(msk)); \
                    reg=tmp; \
                } while (0);

Цитата
И еще - грамотный программист сложное выражение в #define обрамляет в do {} while(0)

А здесь - не могу представить себе пример кода, когда обрамляющие фигурные скобки (блок {} ) работают хуже (да просто не точно так же), как конструкция do {} while (0);
Приведите пример, если можете.
x893
Это очень просто
https://www.google.ru/search?q=зачем+исполь...ile+в+%40define
и читаем первый ответ.
Если есть Яндекс Алиса - можно голосом задать вопрос

https://ru.stackoverflow.com/questions/6801...D1%8F-do-while0
Professor Chaos
Цитата(mihlit @ Sep 2 2018, 05:30) *
1. На просторах Интернета много раз встречал высказывания, что "магическое" число - это не есть хорошо.

Так и есть. Лучше давать таким константам осмысленные имена. Так и читается легче и вносить изменения в код проще.
Цитата
2. ИМХО, работа через регистры более компактна и нагляднее чем применение библиотек.

Компактна - да, возможно, в некоторых случаях. Но далеко не всегда и не везде. Что компактней: в некотором регистре установить какой-то бит в 1 (сбросить бит в 0) или вызвать функцию с 2-3 параметрами? В обоих случаях это будет одна строка кода.
Наглядна - нет. Если бы библиотеки делали код менее наглядным их бы не писали в принципе. А библиотеки как раз и пишутся для повышения наглядности. Они повышают уровень абстракции. Работая с регистрами вам надо знать не только "что делать", но и "как это делать" - какие битовые поля в каких регистрах в какие значения установить. Работая с библиотекой надо знать лишь "что делать". Вопрос "как это сделать" библиотечная функция взяла на себя. Она сама внутри своего тела оперирует регистрами, битами, их позициями в регистрах, сдвигами и масками битовых полей. Снаружи ничего этого не видно и знать не нужно.
Цитата
3. Из п 2. вытекает(для меня), что написание своих макросов и дефайнов не сокращает время долбания клавиатуры и не повышает читаемость кода.

Не сокращает и не повышает.
Но если надо сделать что-то, чего не умеют библиотечные функции, либо сделать то, что могут и они, но как-то по-другому - то для этого пишутся свои функции. Специализированные, под конкретные задачи.

Цитата(x893 @ Sep 2 2018, 08:17) *
Это очень просто

Точно, вспомнил - из-за точки с запятой.
Просто компилятор Кейла допускает конструкцию типа { }; и не ругаются на неё, связывая идущий после этого else с последним if. Так что забыл про этот неприятный момент, хотя и читал про это ранее (забыл уже где).
mihlit
Цитата
Работая с регистрами вам надо знать не только "что делать", но и "как это делать" - какие битовые поля в каких регистрах в какие значения установить. Работая с библиотекой надо знать лишь "что делать". Вопрос "как это сделать" библиотечная функция взяла на себя. Она сама внутри своего тела оперирует регистрами, битами, их позициями в регистрах, сдвигами и масками битовых полей. Снаружи ничего этого не видно и знать не нужно.

Не буду оспаривать очевидное.
Небольшой нюанс - я к МК пришел через проектирование электроники на логических элементах малой степени интеграции, поэтому у меня в крови - знать и понимать что и как я делаю. Чувствую себя не комфортно, если не понимаю, как это действие выполняется.
Сергей Борщ
QUOTE (Professor Chaos @ Sep 2 2018, 08:06) *
Так лучше?
Да. Осталось избавиться от pos, перейдя от (val) << (pos) к (val) * ((msk) & -(msk)). Поскольку и val и msk - константы времени компиляци, замена сдвига на умножение не повлияет на размер и скорость результирующего кода, а в исходнике будет меньше вероятность использовать pos и msk от разных битовых полей.
QUOTE (Professor Chaos @ Sep 2 2018, 08:51) *
Точно, вспомнил - из-за точки с запятой.
Просто компилятор Кейла допускает конструкцию типа { }; и не ругаются на неё, связывая идущий после этого else с последним if.
Надеюсь, что тут вы ошибаетесь. Иначе это был бы компилятор "языка, похожего на Си".
Arlleex
Цитата(Сергей Борщ @ Sep 1 2018, 21:34) *
Кто вас научил такому ужасному ужасу, "библиотеки"? Что будет делать контроллер, получив 1 в нужных позициях и случайные предыдущие значения вместо нулей в остальных (или наоборот, не важно)? Я уже не говорю о лишней записи в регистр. Грамотный программист использует либо конструкцию Reg = (Reg & Mask1) | Mask2, либо ее же, разбитую на два выражения и временную переменную.
И еще - грамотный программист сложное выражение в #define обрамляет в do {} while(0)

Добавлю только, что бывают еще регистры, чувствительные на операции чтения или записи. И двойная запись или двойное чтение может повлиять на работу периферии, к которой этот регистр относится.

Для mihlit:
1. Запись нового значения в регистр
Код
REG = value; // запишет в регистр REG значение value

2. Установка некоторых бит в регистре, не затрагивая значений остальных бит
Код
REG |= value; // установит в REG биты в 1, установленные в двоичном представлении value

3. Сброс некоторых бит в регистре, не затрагивая значений остальных бит
Код
REG &= ~value; // сбросит в REG биты в 0, установленные в двоичном представлении value

4. Одновременные действия пунктов 2 и 3 (было уже озвучено выше)
Код
REG = (REG & Mask1) | Mask2; // сбросит нужные биты по маске Mask1 (там, где у нее 0 в битах) и установит биты по маске Mask2



Цитата(mihlit @ Sep 2 2018, 05:30) *
Объяснюсь по поводу своего вопроса.
1. На просторах Интернета много раз встречал высказывания, что "магическое" число - это не есть хорошо.
2. ИМХО, работа через регистры более компактна и нагляднее чем применение библиотек.
3. Из п2. вытекает(для меня), что написание своих макросов и дефайнов не сокращает время долбания клавиатуры и не повышает читаемость кода.

1. Да, так и есть. Я, например, осмысленные числа, которые еще тем более могут корректироваться в проекте в процессе отладки, заменяю на именованные #define. Пример
Код
#define HW_EEPROM_I2C_ADDRESS             0xA0

#define HW_EXCHANGE_I2C_ADDRESS_OWN       0x12
#define HW_EXCHANGE_I2C_ADDRESS_ABONENT   0x34

В некоторых местах, например, я прибегаю к явным числам, например
Код
if(xSemaphoreTake(MeasureSemaphoreHandle, 50) == pdTRUE) // жду семафор в течение 50мс

В Вашем случае AFRH15 - это 4 старших бита 32-битного регистра AFRH (GPIOx->AFR[1]).
Теперь можно написать что-то вроде
Код
#define AFRH_POS_0 0
...
#define AFRH_POS_15 28
#define AFRH_REG_WRITE(GPIOX, POSITION, VALUE) GPIOX->AFR[1] |= VALUE << POSITION
...
...
...
(в коде)
AFRH_REG_WRITE(GPIOA, AFRH_POS_15, 5);

Здесь устанавливаются нужные биты, заданные числом (5 в данном случае), в позициях битового поля AFRH15 регистра AFRH.
Естественно, можно заморочиться и написать еще более удобнее, но для начинающего менее понятно синтаксически.

2. Не всегда. Меня, например, в некоторых приложениях полностью устраивает библиотека настройки, например, тех же GPIO. Я их настроил, а вот уже дальше - в основном работа через регистры. В общем-то, разницы нет. Можно и через регистры написать свою компактную библиотеку, это не возбраняется.

3. Заблуждение. По мере написания проекта Вы начнете понимать, что Вы полностью этот проект контролируете и разбираетесь в нем. Поверьте, в этом случае, если Вы будете использовать магические числа, будет только хуже. Основное правило - зачем исправлять одну и ту же настройку (например, размер приемного буфера какого-либо интерфейса) в разных местах проекта, если его достаточно поправить в одном определении #define?


Цитата(mihlit @ Sep 2 2018, 08:05) *
Задам еще вопрос по Keil. У меня версия 5.23 (32Кб). Иногда при запуске Keil, теряется какой-то заголовочный файл. Лечится перезагрузкой Keil, но чаще приходится перезагружать Win7. Не смертельно, но иногда задалбывает. Кто- нибудь сталкивался с подобным?

Нужно больше информации. Скрин экрана, например, либо что конкретно пишет среда. У меня такой проблемы нет.


Цитата(Professor Chaos @ Sep 2 2018, 08:06) *
Согласен с замечанием.
Так лучше?
Код
// Макрос записи в регистр reg битовой последовательности val в позицию pos (по младшему разряду)
// msk - маска битового поля
#define TuneBitField(reg,val,pos,msk) \
                do { \
                    tmp=reg; \
                    (tmp) |= (((val) << (pos))&(msk)); \
                    (tmp) &= (((val) << (pos))|~(msk)); \
                    reg=tmp; \
                } while (0);

Точка с запятой после while(0) не нужна.


Цитата(mihlit @ Sep 2 2018, 09:02) *
Не буду оспаривать очевидное.
Небольшой нюанс - я к МК пришел через проектирование электроники на логических элементах малой степени интеграции, поэтому у меня в крови - знать и понимать что и как я делаю. Чувствую себя не комфортно, если не понимаю, как это действие выполняется.

Это хороший подход к делу!
Professor Chaos
Цитата(Сергей Борщ @ Sep 2 2018, 09:07) *
Надеюсь, что тут вы ошибаетесь. Иначе это был бы компилятор "языка, похожего на Си".

Да, ошибся. Проверил. Действительно, выдаёт ошибку.
Это он не ругается на ; после блока в конструкциях вида:
Код
operator1;
{  operator2;
   operator3;
};
operator4;

Код
while (SomeExpr1) {
  if (SomeExpr2) {
    operator1;
    operator2;
  };
}

хотя ; после } там не нужна.
Возможно, он воспринимает ; после } как пустой оператор, поэтому и не имеет ничего против.
mihlit
Цитата
Нужно больше информации. Скрин экрана, например, либо что конкретно пишет среда. У меня такой проблемы нет.

Дык в том то и дело, что стоит крест на, допустим, строчке
#include "stm32f4xx.h"
наводишь стрелку на крест - внизу экрана выводится - "фатальная ошибка: нет пути"
но Keil то работает, т.е можно запустить компиляцию - выдает 0 ошибок, отладка тоже запускается и работает.
Arlleex
Цитата(mihlit @ Sep 2 2018, 11:25) *
Дык в том то и дело, что стоит крест на, допустим, строчке
#include "stm32f4xx.h"
наводишь стрелку на крест - внизу экрана выводится - "фатальная ошибка: нет пути"
но Keil то работает, т.е можно запустить компиляцию - выдает 0 ошибок, отладка тоже запускается и работает.

Include paths прописаны в закладке C/C++ проекта?
У Keil есть такая болезнь, ставить крестики на нормальных строчках. Но не на stm32f4xx.h (у себя ни разу не видел).
mihlit
Цитата
Include paths прописаны в закладке C/C++ проекта?
У Keil есть такая болезнь, ставить крестики на нормальных строчках.

Ест-но. В основном h-файлы из SPL, юзеровских ни разу не видел, вот сегодня "stm32f4xx.h". Поначалу очень нервничал, потом ничего привык - а у него болячка такая оказывается.
Professor Chaos
С макросом оказалось всё немного сложнее.
При введении в него промежуточной переменной tmp появилась необходимость указывать её тип. Он должен совпадать с типом reg. А т.к. он в общем случае разный и заранее неизвестный, то придётся его вводить одним из параметров макроса.
Как-то так
Код
// Макрос записи в регистр reg битовой последовательности val
// в позицию pos (по младшему разряду), msk - маска битового поля
#define TuneBitField(typename,reg,val,pos,msk) \
  do { \
      typename tmp=reg; \
      tmp |= (((val) << (pos))&(msk)); \
      tmp &= (((val) << (pos))|~(msk)); \
      reg=tmp; \
  } while (0)

В С++ этот макрос можно (а скорее нужно) переоформить в виде шаблонной подставляемой (inline) функции, где параметром шаблона как раз и будет имя типа регистра reg, а аргументом функции будет ссылка на регистр, чтобы его содержимое можно было изменить.
Второй вариант выхода из ситуации (для Си без плюсов) - переписать макрос без использования промежуточной переменной, приведя его к виду: do {reg=(reg&msk1)|msk2;} while (0)
Код
// Макрос записи в регистр reg битовой последовательности val
// в позицию pos (по младшему разряду), msk - маска битового поля
#define TuneBitField(reg,val,pos,msk) \
    do { \
      reg = ((reg)&(((val) << (pos)))|~(msk))|(((val) << (pos))&(msk)); \
    } while (0)
jcxz
Цитата(Professor Chaos @ Sep 2 2018, 15:48) *
// в позицию pos (по младшему разряду), msk - маска битового поля
#define TuneBitField(typename,reg,val,pos,msk) \
do { \
typename tmp=reg; \
tmp |= (((val) << (pos))&(msk)); \
tmp &= (((val) << (pos))|~(msk)); \
reg=tmp; \
} while (0)[/code]

Это-ж как так надо запутать простейшее выражение?? :
Пользуйтесь: rolleyes.gif
reg = ((reg) & ~(msk)) | ((val) << (pos) & (msk));
Либо так:
reg = ((reg) | (msk)) ^ (~(val) << (pos) & (msk));
и никаких промежуточных переменных....
Professor Chaos
Цитата(jcxz @ Sep 2 2018, 17:20) *
Пользуйтесь: rolleyes.gif
reg = ((reg) & ~(msk)) | ((val) << (pos) & (msk));


Спасибо.
Так, вероятно, проще всего. И понятней.
Сразу виден алгоритм: сначала зануляем всё битовое поле целиком ((reg) & ~(msk)), после чего выставляем в нем 1 в нужных разрядах ( | ((val) << (pos) & (msk)) ).
mihlit
Задал вопрос в отдельной ветке - молчок. Буду спрашивать здесь.
Передача данных от ADC в буфер по DMA.
Код
ADC_Config();        // ADC configuration
ADC_SoftwareStartConv(ADC1);    // Start ADC1 Software Conversion
while (1)
{
    while(!DMA_LISR_TCIF0) continue;    //ждать заполнения буфера
         // обработка буфера
}

DMA в режиме Normal
Первый цикл проходит - буфер заполнился.
Смотрю RM0090 в разделе ADC 13.8.1 (перевод Google)
"Чтобы восстановить ADC из состояния OVR, когда используется DMA, выполните следующие действия:
1. Повторно инициализировать DMA (настроить адрес назначения и счетчик NDTR)
2. Очистите бит ADV OVR в регистре ADC_SR
3. Запустите АЦП, чтобы начать преобразование."

Выполнил первый пункт.
Со вторым непонятки.
Если в ADC установлен флаг CONT то флаг OVR не сбрасывается. При сбросе CONT флаг OVR может сброситься, но чаще - нет.
То же самое с флагом STRT.
Что не так делаю?
mihlit
Извиняйте за компанию
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.