Ярлыки

_GetPixelIndex (1) _SetPixelIndex (1) 3-phase (1) 800x480 (1) АЦП (1) генератор (1) синхронный усилитель (2) структура (1) учебный курс (1) шаговый двигатель (1) ШИМ (2) accert (1) AD7608 (1) AD8429 (1) ADC (5) amplifer (1) arccos (1) arcsin (1) arctang (2) arctg (3) ARM (2) arm_sqrt_q15 (2) assembler (6) ASSERT (1) atan (2) bit (1) Bitband (1) boot (3) bootlloader (1) BUTTON (1) C (5) C# (1) CAN (2) CC2530 (5) CMSIS (4) command (1) Cordic (1) Core746I (1) CubeMX (4) DBGMCU (2) debug (2) debug.ini (1) delegate (1) Digital Potentiometers (1) DigitalPOT (1) Discovery (1) DMA (9) DMA2D (1) DSP (1) DSP library (1) DWT (1) EFM32 (5) EmWin (9) EXTI (1) FATFS (1) FMC (2) FreeRTOS (2) gl868-dual cmux (1) GPIO (4) GUI (2) GUIBuilder (1) GUIDRV_CompactColor_16 (1) HAL (3) HappyGecko (1) Hard Fault (2) heap (1) I2C (1) ID (1) ILI9320 (1) ILI9325 (1) Initialisation (1) InitLTDC (1) Instrumentithion (1) Interrupt (4) ITR (1) JTAG (1) Keil (5) LCDConf (2) lock-in (1) LTCD (1) LTDC (3) main (1) memory (1) MINI_STM32 Revision 01 (1) nBoot0 (1) NVIC (1) OnePulse (2) OSAL (4) pack (1) phase (1) printf (3) Pulse (1) PWM (12) RCC (2) RCR (1) Register (1) RESET (2) RS232 (3) RSS (1) RTC (3) RTOS-RTX (1) RTT (1) RTX-RTOS (1) SDCard (1) SDRAM (6) Segger (2) SPI (3) sqrt (3) SSD1298 (1) SSD1963 (1) Standart Peripherial Library (3) STANDBAY (1) startup (1) STemWin (8) stepper motor (1) STlink (2) STM32 (17) STM32429ZI (1) STM32Cube (1) STM32DBG.IN (1) STM32F (28) STM32F0 (4) STM32F1 (13) STM32F4 (10) STM32F4 Discovery (1) STM32F407ZG (1) STM32F429 (2) STM32F746 (1) STOP (1) string (1) struct (1) SWD (1) SWD JTAG (1) Synhronization (1) system_stm32f4xx.c (1) SystemInit (1) SysTick (1) task (4) telit (1) TIM (27) typedef (1) UART (1) USART (9) viewer (2) WM_PAINT (1) Z-stack (5) ZigBee (5)

суббота, 29 ноября 2014 г.

Настройка преобразования первых 8ми регулярных каналов АЦП с использованием канала DMA

void ADC_init(void)
{
// настройка ADC1
        RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //  такты на ADC1

        ADC1->SMPR2 |= ADC_SMPR2_SMP0 | ADC_SMPR2_SMP1 
        | ADC_SMPR2_SMP2 | ADC_SMPR2_SMP3 | ADC_SMPR2_SMP4 
        | ADC_SMPR2_SMP5 | ADC_SMPR2_SMP6 | ADC_SMPR2_SMP7;       // количество циклов преобразования 239.5

        ADC1->SQR1 |= ADC_SQR1_L_2 | ADC_SQR1_L_1 | ADC_SQR1_L_0; // длина последовательности регулярных каналов = 8;
        // добавление в последовательность каналов
        ADC1->SQR2 |= ADC_SQR2_SQ8_2 | ADC_SQR2_SQ8_1 | ADC_SQR2_SQ8_0 //канал 7
        | ADC_SQR2_SQ7_2 | ADC_SQR2_SQ7_1;                             // канал 6

        ADC1->SQR3 |=  ADC_SQR3_SQ6_2 | ADC_SQR3_SQ6_0                 //канал 5
        | ADC_SQR3_SQ5_2                                               //канал 4
        | ADC_SQR3_SQ4_1 | ADC_SQR3_SQ4_0                              //канал 3
        | ADC_SQR3_SQ3_1                                               //канал 2
        | ADC_SQR3_SQ2_0;                                              // канал 1
        //канал 0 включен по умолчанию т.к. в младших битах SQ3 0
//      ADC1->CR2 |= ADC_CR2_CONT;      // включаем если нужно непрерывное преобразование последовательности в цикле

        ADC1->CR2 |= ADC_CR2_DMA //включаем работу с DMA
        | ADC_CR2_EXTTRIG //включаем работу от внешнего события 
        | ADC_CR2_EXTSEL //выбираем триггером запуска регулярной последовательности событие SWSTART
        | ADC_CR2_JEXTSEL; // выбираем триггером запуска выделенной последовательности событие JSWSTART дабы эти каналы не отнимали у мк времени
        ADC1->CR1 |= ADC_CR1_SCAN; // включаем автоматический перебор всех каналов в последовательности
//макросы для включения/выключения АЦП с DMA
#define ADC_ON ADC1->CR2 |= ADC_CR2_ADON;  \
                                ADC1->CR2 |= ADC_CR2_SWSTART; \
                                DMA1_Channel1->CCR |= DMA_CCR1_TCIE | DMA_CCR1_EN;      //включаем преобразование прерывание DMA
#define ADC_OFF ADC->CR2 &= (~(ADC_CR2_ADON)); \
                                DMA1_Channel1->CCR &= (~(DMA_CCR1_TCIE | DMA_CCR1_EN)); //выключаем преобразование и прерывание DMA
        
        return;
}


Настройка DMA для АЦП


        DMA1_Channel1->CPAR = ADC1_BASE+0x4C; // Загружаем адрес регистра DR
        DMA1_Channel1->CMAR = pADC_readbuf_addr->Buf_Addr; //грузим адрес буфера обмена
        DMA1_Channel1->CNDTR = 8; //длина буфера 
        DMA1_Channel1->CCR |= DMA_CCR1_MINC     //инкремент адреса памяти
        | DMA_CCR1_PSIZE_0 //размерность данных периферии 16 бит
        | DMA_CCR1_MSIZE_0 //размерность данных памяти 16 bit
        | DMA_CCR1_CIRC;   // закольцевать буфер

SPI2 в режиме мастера для работы с DMA

void SPI_init(void)
{
// SPI2 init
        RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; // такты на SPI2

        GPIOB->CRH &= (~(GPIO_CRH_CNF13_0 | GPIO_CRH_CNF15_0)); //настройка выводов для SPI
        GPIOB->CRH |= (GPIO_CRH_MODE13 | GPIO_CRH_MODE15                
         | GPIO_CRH_CNF13_1 | GPIO_CRH_CNF15_1);                // AF Push-Pull out

        SPI2->CR1 |= SPI_CR1_BR_1    //настройка делителя 
//       | SPI_CR1_BR_0    //комментируя или раскомментируя эти строки можно изменять значение делителя 
//       | SPI_CR1_BR_2
         | SPI_CR1_SSM   // программное управление слэйвом
         | SPI_CR1_SSI   // при программном управлении слэйвом данный бит должен быть 1
         | SPI_CR1_MSTR  // Режим мастера
         | SPI_CR1_SPE;   // разрешить SPI2 

        SPI2->CR2 |= SPI_CR2_RXDMAEN // разрешить передачу принятых данных через DMA
         | SPI_CR2_TXDMAEN; // Разрешить принимать данные для передачи через DMA

        return;
}

DMA для работы с SPI2 на прием и передачу



        RCC->AHBENR |= RCC_AHBENR_DMA1EN; //такты

        // 4 канал DMA1  RX SPI2 -> память
        DMA1_Channel4->CPAR = SPI2_BASE+0x0C; // адрес DR
        DMA1_Channel4->CMAR = pSPI2_readbuf_addr->Buf_Addr; //адрес буфера приема
        DMA1_Channel4->CNDTR = 12; // размер транзакции
        DMA1_Channel4->CCR |= DMA_CCR4_MINC     //инкремент адреса буфера
        | DMA_CCR4_PSIZE_0;     //размерность данных SPI 16 бит (происходит автоматическое преобразование 16->8 бит)

        // 5 канал DMA1  память -> TX SPI2
        DMA1_Channel5->CPAR = SPI2_BASE+0x0C; //адрес DR
        DMA1_Channel5->CMAR = pSPI2_writebuf_addr->Buf_Addr; //адрес буфера передачи
        DMA1_Channel5->CNDTR = 12; // размер транзакции
        DMA1_Channel5->CCR |= DMA_CCR5_MINC     //инкремент адреса буфера
        | DMA_CCR5_DIR; // направление передачи из памяти в периферию


Транзакция запускается следующим куском кода:


void SPI2_start (void) // По сути это переинициализация каналов DMA
{
        DMA1_Channel4->CPAR = SPI2_BASE+0x0C; //DR Base 
        DMA1_Channel4->CMAR = pSPI2_readbuf_addr->Buf_Addr;
        DMA1_Channel4->CNDTR = 12;
        DMA1_Channel5->CPAR = SPI2_BASE+0x0C; //DR Base
        DMA1_Channel5->CMAR = pSPI2_writebuf_addr->Buf_Addr;
        DMA1_Channel5->CNDTR = 12;
        DMA1_Channel4->CCR |= DMA_CCR4_TCIE | DMA_CCR4_EN;
        DMA1_Channel5->CCR |= DMA_CCR5_EN;
        return;
}


Результаты обрабатываются по прерыванию завершения работы канала DMA работающего на прием данных от SPI:


void DMAChannel4_IRQHandler     (void)
{
        DMA1_Channel4->CCR &= (~(DMA_CCR4_TCIE | DMA_CCR4_EN)); // выключаем канал приемника и его прерывание
        DMA1->IFCR |= DMA_IFCR_CTCIF4 | DMA_IFCR_CGIF4; //очищаем флаги
        DMA1_Channel5->CCR &= (~(DMA_CCR5_EN)); // выключаем канал передатчика
        pCurrent_mode->stat.led_data_send = 0; // выставляем нужные флаги для дальнейшей работы с данными 
        HC595_OUT;
        pCurrent_mode->stat.read_key_data_ready=1;
        return;
}

ШИМ по двум каналам на TIM1

RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;  //такты
TIM1->CCER = 0;                     //обнуляем CCER (выключаем каналы)
TIM1->ARR = 100;                 // максимальное значение, до которого таймер ведет счет 
TIM1->PSC = 7200-1;                // предделитель         
TIM1->BDTR |= TIM_BDTR_MOE;     // Разрешаем вывод сигнала на выводы
//для первого ШИМ-сигнала используем канал 1 
//задаем скважность в регистр сравнения канала (значения от 0 до TIM1->ARR) 
TIM1->CCR1 = 50;      
// Включаем режим канал в режим ШИМ           
TIM1->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;     
// Разрешаем вывод не инвертированного сигнала на ногу МК     
TIM1->CCER |= TIM_CCER_CC1E;     
// Разрешаем вывод не инвертированного сигнала на ногу МК 
//для второго ШИМ-сигнала используем канал 4
//задаем скважность в регистр сравнения канала (значения от 0 до TIM1->ARR)   
TIM1
->CCR4 = 50;                   
// Включаем канал в режим ШИМ       
TIM1->CCMR2 |= TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2;     
// Разрешаем вывод не инвертированного сигнала на ногу МК
TIM1
->CCER |= TIM_CCER_CC4E;     
// Запускаем счет
TIM1
->CR1 |= TIM_CR1_CEN;



Теперь для управления скважностью нужного канала меняем значения в регистрах TIM1->CCR1 и TIM1->CCR4. Т.к. у нас глубина счета установлена 100, то задавая значение от 0 до 100 получим скважность в процентах :)