• Объявления

    • admin

      Просьба всем принять участие!   24.11.2017

      На форуме разыгрывается спектроанализатор Arinst SSA-TG LC (цена 18500 руб). Просьба всем перейти по ссылке ниже и принять участие!

FrostedVic

Members
  • Публикации

    8
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

О FrostedVic

  • Звание
    Новенький

Информация

  • Город
    москва

Электроника

  • Стаж в электронике
    1-2 года
  1. Stm32F4 Adc. Режимы Работы. Помогите Разобраться.

    Вроде как разобрался! Проблема была в том, чо я неправильно задал соответсвие между каналом АЦП и пином с которого снимаю сигнал(((В итоге для регулярных каналов: #include "stm32f4xx.h" uint32_t LED_STATE = 0xF000; uint32_t res; int main() { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN|RCC_AHB1ENR_GPIODEN; RCC->APB2ENR |= RCC_APB2ENR_ADC1EN|RCC_APB2ENR_SYSCFGEN; GPIOA->MODER |= 0x0000000C; GPIOD->MODER |= 0x55000000; GPIOD->OTYPER |= 0; GPIOD->OSPEEDR |= 0; ADC1->SMPR2 |= (ADC_SMPR2_SMP1_2 | ADC_SMPR2_SMP1_1 | ADC_SMPR2_SMP1_0); //Задаем время выборки ADC1->CR2 |= ADC_CR2_EXTSEL; //Преобразование инжектированной группы ADC1->CR2 |= ADC_CR2_EXTEN; //Разрешаем внешний запуск инжектированной группы ADC1->CR2 |= ADC_CR2_CONT; //Преобразования запускаются одно за другим ADC1->SQR3 |= ADC_SQR3_SQ1_0; //Задаем номер канала - ADC1 ADC1->CR2 |= ADC_CR2_ADON;//Теперь включаем АЦП while(1) { ADC1->CR2 |= ADC_CR2_SWSTART; //Запуск преобразований while (!(ADC1->SR & ADC_SR_EOC)); //ждем пока первое преобразование завершится ADC1->SR = 0; res = ADC1->DR; if (res > 1024) { GPIOD->ODR = LED_STATE; } else { GPIOD->BSRRH |= (1 << 15)|(1 << 14)|(1 << 13)|(1 << 12); } } } Для инжектированных: #include "stm32f4xx.h" uint32_t LED_STATE = 0xF000; uint32_t res; int main() { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN|RCC_AHB1ENR_GPIODEN; RCC->APB2ENR |= RCC_APB2ENR_ADC1EN|RCC_APB2ENR_SYSCFGEN; GPIOA->MODER |= 0x0000000C; GPIOD->MODER |= 0x55000000; GPIOD->OTYPER |= 0; GPIOD->OSPEEDR |= 0; ADC1->SMPR2 |= (ADC_SMPR2_SMP1_2 | ADC_SMPR2_SMP1_1 | ADC_SMPR2_SMP1_0); //Задаем время выборки ADC1->CR2 |= ADC_CR2_JEXTSEL; //Преобразование инжектированной группы ADC1->CR2 |= ADC_CR2_JEXTEN; //Разрешаем внешний запуск инжектированной группы ADC1->CR2 |= ADC_CR2_CONT; //Преобразования запускаются одно за другим ADC1->CR1 |= ADC_CR1_JAUTO; //ADC1->CR1 |= 0x00000020; ADC1->JSQR |= ADC_JSQR_JSQ4_0; //Задаем номер канала - ADC1 ADC1->CR2 |= ADC_CR2_ADON;//Теперь включаем АЦП while(1) { ADC1->CR2 |= ADC_CR2_JSWSTART; //Запуск преобразований while (!(ADC1->SR & ADC_SR_JEOC)); //ждем пока первое преобразование завершится ADC1->SR = 0; res = ADC1->JDR1; if (res > 1024) { GPIOD->ODR = LED_STATE; } else { GPIOD->BSRRH |= (1 << 15)|(1 << 14)|(1 << 13)|(1 << 12); } } } Еще попробую разобраться с прерываниями по EOC
  2. Я начал разбираться с АЦП на STM32F4Discovery. Вычитал, что у АЦП существуют два метода опроса: регулярные каналы и инжектированные каналы. Разницу между ними я более менее понял. Первая группа запись данных в один регистр, вторая группа результат можно записать в один из 4-х регистров. Я стараюсь писать код используя CMSIS. К порту PA1 прикрутил переменный резистор, и по изменению значения должны зажигаться диоды на PD12, 13, 14, 15 но почему-то не работает, подскажите пожалуйста что не так. #include "stm32f4xx.h" uint32_t LED_STATE = 0xF000; uint32_t res; int main() { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN|RCC_AHB1ENR_GPIODEN; RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //GPIOA->MODER |= 0x0000000C; GPIOD->MODER |= 0x55000000; GPIOD->OTYPER |= 0; GPIOD->OSPEEDR |= 0; ADC1->SMPR2 |= (ADC_SMPR2_SMP1_2 | ADC_SMPR2_SMP1_1 | ADC_SMPR2_SMP1_0); //Задаем время выборки ADC1->CR2 |= ADC_CR2_JEXTSEL; //Преобразование инжектированной группы ADC1->CR2 |= ADC_CR2_JEXTEN; //Разрешаем внешний запуск инжектированной группы ADC1->CR2 |= ADC_CR2_CONT; //Преобразования запускаются одно за другим ADC1->CR1 |= ADC_CR1_JAUTO; ADC1->JSQR |= (1<<15); //Задаем номер канала - ADC1 ADC1->CR2 |= ADC_CR2_ADON;//Теперь включаем АЦП ADC1->CR2 |= ADC_CR2_JSWSTART; //Запуск преобразований while (!(ADC1->SR & ADC_SR_JEOC)); //ждем пока первое преобразование завершится while(1) { res = ADC1->JDR1; if (res > 1024) { GPIOD->ODR=LED_STATE ; } } }[/background][/size][/font][/color] [color=#000000][font=Verdana, Arial, Helvetica, sans-serif][size=3][background=rgb(255, 255, 204)] Поскольку я разбираюсь в режимах преобразования, то я так же пробовал написать код и для регулярных каналов: #include "stm32f4xx.h" uint32_t LED_STATE = 0xF000; int main() { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN|RCC_AHB1ENR_GPIODEN; RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; GPIOA->MODER |= 0x0000000C; GPIOD->MODER |= 0x55000000; GPIOD->OTYPER |= 0; GPIOD->OSPEEDR |= 0; ADC1->SMPR2 |= (ADC_SMPR2_SMP1_2 | ADC_SMPR2_SMP1_1 | ADC_SMPR2_SMP1_0); ADC1->CR2 |= ADC_CR2_EXTSEL; ADC1->CR2 |= ADC_CR2_EXTEN; ADC1->CR2 |= ADC_CR2_CONT; ADC1->SQR1 |= (1<<15); //Задаем номер канала - ADC1 ADC1->CR2 |= ADC_CR2_ADON;//Теперь включаем АЦП ADC1->CR2 |= ADC_CR2_SWSTART; //Запуск преобразований while (!(ADC1->SR & ADC_SR_EOC)); //ждем пока первое преобразование завершится uint32_t res; while(1) { res = ADC1->DR; if (res > 1024) { GPIOD->ODR=LED_STATE ; } } } Но он тоже не работает(((
  3. Здравствуйте! Помогите пожалуйста разобраться с прерываниями. Вернее с тем как их настраивать используя только CMSIS. Мой девайс STM32F4DISCOVERY программирую под IARом. Для структуризации разделю свои вопросы на две части по внутренним прерываниям и по внешним. Логичнее начать с внутренних. NVIC Разрешение прерываний. С функцией NVIC_EnableIRQ(IRQ) все понятно, просто запихнуть в ее аргумент нужный обработчик. Вопрос как разрешить прерывания с использованием регистров. Насколько я понял для разрешения прерываний используется регистр ISER, более того он разбит на три элемента. Вот тут и возникает вопрос. Как используя тот или иной элемент разрешить прерывания по нужной мне периферии? Например USART Приоритеты и группы приоритетов прерываний Вот здесь для меня вообще темный лес. Как с помощью регистров расставлять приоритеты? IPRx как раз отвечает за приоритет. Но их 20 шутк Как определить какой из них отвечает за выставление приоритета у того же USART и какой байт мне нужен? Что касается подгрупп то дело еще темнее. Вообще читая RM часто вижу обозначение РЕГИСТР[x:y] например: AIRCR[10:8] что в скобках? Как я могу это использовать? EXTI Собственно вопросы те же самые. Единственное, что хочу прописать здесь для собственного понимания это то, что для прерываний по состоянию ножки эту самую ножку я должен сконфигурировать как альтернативную функцию. Про софтверный вызов я пока молчу. Если быть конкретнее, то вот вопросы: У нас 16 линий EXTI каждому номеру соответствует номер порта, то есть EXTI1 отвечает за ножки номер 1 портов A-E (в моем случае) Но как назначить порт? Далее непонятно, если у нас 16 линий EXTI0-EXTI15, то что такое EXTI0_IRQn до EXTI4_IRQn и EXTI5_9_IRQn и EXTI10_15IRQn В примерах кода видел такую запись: AFIO->EXTICR[1] AFIO - очевидно, что-то связанное с Альтернативной функцией. Посмотрел в IAR у меня подобного нет, но есть SYSCFG->EXTICR[1] или эти вещи не связаны? Еще что такое EXTICR[1] (в заголовках вообще объявлен массив из 4-х элементов)? Ну и собственно непонятен опять же момент с разрешением прерываний с использование регистра IMR. Вот я выбрал ногу микроконтроллера, вот я выбрал порт. Как разрешить именно это прерывание? Уффф. Пока все. Вопросов много. Не пинайте, я честно сидел и разбирался в примерами и читал RM. Отсюда и возникли вопросы.
  4. Снова здравствуйте!) Перешел к изучению SysTck Рассмотрел примеры, в которых на основе этого таймера делается функция задержки. И возник вопрос. Можно ли в прерывании генерируемом этим счетчиком включать LED? Или шпилька будет настолько короткой, что я ее не увижу? Грубо говоря написать так: void SysTick_Handler(void) { GPIOD->BSRRL |= ( 1<<12 ); } int main() { RCC->AHB1ENR = RCC_AHB1ENR_GPIODEN;//RCC -название модуля; AHB1ENR -название регистра; GPIODEN -устанавливаемый бит /*---Конфигурируем GPIO порт D---*/ GPIOD->MODER =0x55000000;/*Регистр установки режима порта вход/выхода для 12, 13, 14, 15 линий порта D 0x55000000 это шестнадцатеричное представление числа 010101010000000000000000000000, где 01 -конфигурация регистра MODER на выход. 0101 в двоичной системе = 5 в шестнадцатиричной*/ GPIOD->OTYPER = 0;// Регистр установки режима порта с подтяжкой или открытым коллектором GPIOD->OSPEEDR = 0; //Регистр установки скорости работы порта SysTick_Config(TimerTick); while(1) { GPIOD->BSRRH |= ( 1 << 12 );//Устанавливаем низкий уровень на 12-й линии } }
  5. Вопросы По Регистрам Gpio

    Пишу в IAR Код программы: #include "stm32f4xx.h" void sysDelay(uint32_t delay) { for (int i = 0; i < delay; i++); } int main() { RCC->AHB1ENR = RCC_AHB1ENR_GPIODEN;//RCC -название модуля; AHB1ENR -название регистра; GPIODEN -устанавливаемый бит /*---Конфигурируем GPIO порт D---*/ GPIOD->MODER =0x55000000;/*Регистр установки режима порта вход/выхода для 12, 13, 14, 15 линий порта D 0x55000000 это шестнадцатеричное представление числа 010101010000000000000000000000, где 01 -конфигурация регистра MODER на выход. 0101 в двоичной системе = 5 в шестнадцатиричной*/ GPIOD->OTYPER |= 0x82;// Регистр установки режима порта с подтяжкой или открытым коллектором volatile uint32_t j = GPIOD->OTYPER; GPIOD->OSPEEDR = 0; //Регистр установки скорости работы порта while(1) { GPIOD->BSRRL |= ( 1 << 12 );//Устанавливаем высокий уровень на 12-й линии sysDelay(500000);//устанавливаем задержку GPIOD->BSRRL |= ( 1 << 13 );//Устанавливаем высокий уровень на 13-й линии sysDelay(500000); GPIOD->BSRRL |= ( 1 << 14 );//Устанавливаем высокий уровень на 14-й линии sysDelay(500000); GPIOD->BSRRL |= ( 1 << 15 );//Устанавливаем высокий уровень на 15-й линии sysDelay(500000); GPIOD->BSRRH = GPIO_BSRR_BS_12;//Устанавливаем внизкий уровень на 12-й линии sysDelay(500000); GPIOD->BSRRH = GPIO_BSRR_BS_13;//Устанавливаем внизкий уровень на 13-й линии sysDelay(500000); GPIOD->BSRRH = GPIO_BSRR_BS_14;//Устанавливаем внизкий уровень на 14-й линии sysDelay(500000); GPIOD->BSRRH = GPIO_BSRR_BS_15;//Устанавливаем внизкий уровень на 15-й линии } } А не могли бы вы на примере пояснить как тогда устанавливать MODER с помощью этих бит (MODER0_0 и т.д.), что-то я не совсем понимаю. Спасибо
  6. Вопросы По Регистрам Gpio

    1. Это найдено в заголовочном файле) 2. То есть для нулевого состояния константы просто нет? 3. Ну вопрос скорее не в переводе из одной системы в другую, а в применимости этого перевода при установке регистров. По невозможности установки двоичного значения, я предполагаю, что компилятор воспринимает мое двоичное число как int причем очень большое и вылезающее за рамки инта. Видимо должна быть какая-то правильная форма записи двоичных чисел. Пробовал 0bxxxxxxxxxxx... ругается на отсутствие ; после перед b Так вот при прочтении мануала и сопоставлении его с заголовочными файлами и возникли вопросы)))
  7. Вопросы По Регистрам Gpio

    Здравствуйте уважаемые форумчане. Начал изучение stm32f4, имея на руках платку discovery. Решил помигать диодиками. В процессе изучения Reference manual и ознакомления с заголовочным файлом stm32f4xx.h появились вопросы. 1. В заголовочных файлах есть описания регистров BSRRL и BSRRH один регистр GPIO port bit set/reset low register другой GPIO port bit set/reset high register. Прошу пояснения в чем разница между ними? 2. Так же в том же файле есть описания #define GPIO_MODER_MODER0 ((uint32_t)0x00000003) #define GPIO_MODER_MODER0_0 ((uint32_t)0x00000001) #define GPIO_MODER_MODER0_1 ((uint32_t)0x00000002) И так на каждую лини по три таких строчки MODER -это регистр установки линии порта на вход выход, аналоговый сигнал или режим альтернативного функционирования. Вот и возник вопрос почему режима четыре, а строчки три? Или я чего-то не понял? А еще совсем нубский вопрос касающийся шестнадцатиричных чисел. И записи в регистр какого-либо значения. Допустим есть регистр MODER. Чтобы проинициализировать каждый вывод регистра надо 2 бита. 16 линий => 32 бита надо установить. Пусть 15, 14, 13, 12 линии я конфигурирую как 01, значит в регистр я должен записать 01010101000000000000000000000000 (это двоичная система-верно? ноль вначале можно откинуть?). Теперь к вопросу. Я в примерах встречал что эта запись аналогична записи в 16х системе 0х55000000 собственно как это получается? И почему у меня в наглую не получилось записать в регистр MODER двоичное число? Спасибо за ответ
  8. Всем привет! Возник вопрос о том как осуществить передачу данных по UART. #include "msp430.h" /* * main.c */ //const char string[] = { "Hello World\r\n" }; void initADC(void); int tempOUT(void); void initUART(); int main(void) { int t ; WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer initADC(); initUART(); //__bis_SR_register(CPUOFF + GIE); while(1) { __delay_cycles(1000);//Сюда нужно передавать задержку переданную с компа t = tempOUT(); __delay_cycles(1000);//...и сюда } return 0; } void initADC() { ADC10CTL0 = SREF_1 + ADC10SHT_2 + REFON + ADC10ON; // Включаем АЦП ADC10CTL1=INCH_10+ ADC10DIV_3;//Канал с которого ведется преобразование 10(INCH_10) //ADC10DIV_3- контролирует время разрешенное на преобразование } int tempOUT() { int T = 0; int tmp = 0; ADC10CTL0 |= ENC + ADC10SC; //Включаем преобразование когда ENC = 1 //Начинам преобразование, когда ADC10SC = 1 while(ADC10CTL1 & ADC10BUSY); T = ADC10MEM; ADC10CTL0&=~ENC; tmp = (0.413 * T - 277.7 ); return(int)(tmp); } void initUART() { P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD P1SEL2 = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD UCA0CTL1 |= UCSWRST; // Этот бит блокирует работу прерываний от UART и работу // сдвигового регистра чтобы не мешать // настройке (грубо говоря отключает UART). UCA0CTL1 |= UCSSEL_2; // Наш UART будет работать от // SMCLK (Sub-main clock), тоесть от 1MHZ. UCA0BR0 = 0x03; // Делитель частоты для SMCLK (1000000 / 9600). UCA0BR1 = 0x03; UCA0MCTL = UCBRS1 + UCBRS0; // Модуляция UCBRSx = 3 UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** IE2 |= UCA0RXIE; // Включаем UART обратно. } /*void UARTWriteString(char ch) { //тестовый посыл в uart-порт int strSize = sizeof(); for(int i = 0; i < strSize; i++) { //WDTCTL = WDTPW + WDTCNTCL; // Сброс таймера watchdog в ноль. while (!(IFG2&UCA0TXIFG)) ; // Проверка готовности буфера отправки. UCA0TXBUF = str[i]; } }*/ Как инициализировать я разобрался. А вот как передать значение температуры догнать не могу. На хабре наткнулся на статью http://habrahabr.ru/post/137719/ .Там все просто для понимания, однако string в заголовках вроде бы не отвечает стандарту Си. Нашел еще примеры с прерываниями, и реализация на таймере. И тут совсем запутался. Как все-таки осуществить прием и передачу данных? Какие тонкости? Заранее благодарю!