Ярлыки

_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)
Показаны сообщения с ярлыком GPIO. Показать все сообщения
Показаны сообщения с ярлыком GPIO. Показать все сообщения

пятница, 8 ноября 2013 г.

Обращение к GPIO

Ко многим ресурсам STM32 можно обратиться как к слову (32бит), полуслову (16бит) и как к байту (8бит). Например, так:

#define GPIOB_Low             (*(__IO uint8_t *)((uint32_t)&(GPIOB->ODR)))
#define GPIOB_High            (*(__IO uint8_t *)((uint32_t)&(GPIOB->ODR) + 1))

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

Например запись

#define LCD_DATA             (*(__IO uint8_t *)((uint32_t)&(GPIOB->ODR)))
LCD_DATA = 0xA5;

позволяет очень просто оперировать шиной LCD 8бит, подключённой к PB0-PB7..

четверг, 7 ноября 2013 г.

STM32 GPIO

Datasheet fom st.com

STM32F103xC, STM32F103xB - техническое описание, цоколевка, характеристики, обзор, схемы подключения, габариты (CD00161566)

STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx, STM32F107xx - справочное руководство, описание структуры и регистров( RM0008)

Standard Peripheral Library 

stm32f10x_gpio.h  stm32f10x_gpio.c - GPIO_InitTypeDef (GPIO_PIN, GPIO_Speed, GPIO_Mode)

stm32f10x_rcc.c и stm32f10x_rcc.h. - тактирование

Режимы работы портов GPIO
  • Input floating
  • Input pull-up
  • Input-pull-down
  • Analog
  • Output open-drain
  • Output push-pull
  • Alternate function push-pull
  • Alternate function open-drain
Keil
la porta&0×01

Управление портами STM32 осуществляется при помощи наборов из семи 32-разрядных регистров:

GPIOx_CRL, GPIOx_CRH – задают режимы работы каждого из битов порта в качестве входа или выхода, определяют конфигурацию входных и выходных каскадов.
GPIOx_IDR – входной регистр данных для чтения физического состояния выводов порта x.
GPIOx_ODR– выходной регистр осуществляет запись данных непосредственно в порт.
GPIOx_BSRR – регистр атомарного сброса и установки битов порта.
GPIOx_BSR – регистр сброса битов порта.
GPIOx_LCKR – регистр блокировки конфигурации выводов.



Для включения в работу порта x необходимо предварительно подключить его к шине APB2 установкой соответствующего бита IOPxEN в регистре разрешения тактирования периферийных блоков RCC_APB2ENR:

RCC->APB2ENR |= RCC_APB2ENR_IOPxEN; // Разрешить тактирование PORTx.

Режимы работы отдельных выводов определяются комбинацией битов MODEy[1:0] и CNFy [1:0] регистров GPIOx_CRL и GPIOx_CRH (здесь и далее: x-имя порта, y- номер бита порта).

GPIOx_CRL — регистр конфигурации выводов 0…7 порта x:



Структура регистра GPIOx_CRH аналогична структуре GPIOx_CRL и предназначена для управления режимами работы старших выводов порта (биты 8…15).
Биты MODEy указанных регистров определяют направление вывода и ограничение скорости переключения в режиме выхода:

MODEy[1:0] = 00: Режим входа (состояние после сброса);
MODEy[1:0] = 01: Режим выхода, максимальная скорость – 10МГц;
MODEy[1:0] = 10: Режим выхода, максимальная скорость – 2МГц;
MODEy[1:0] = 11: Режим выхода, максимальная скорость – 50МГц.
Биты CNF задают конфигурацию выходных каскадов соответствующих выводов:
в режиме входа:

CNFy[1:0] = 00: Аналоговый вход;
CNFy[1:0] = 01: Вход в третьем состоянии (состояние после сброса);
CNFy[1:0] = 10: Вход с притягивающим резистором pull-up (если PxODR=1) или pull-down (если PxODR=0);
CNFy[1:0] = 11: Зарезервировано.
в режиме выхода:

CNFy[1:0] = 00: Двухтактный выход общего назначения;
CNFy[1:0] = 01: Выход с открытым стоком общего назначения;
CNFy[1:0] = 10: Двухтактный выход с альтернативной функцией;
CNFy[1:0] = 11: Выход с открытым стоком с альтернативной функцией.
С целью повышения помехоустойчивости все входные буферы содержат в своём составе триггеры Шмидта. Часть выводов STM32, снабженных защитными диодами, соединёнными с общей шиной и шиной питания, помечены в datasheet как FT (5V tolerant) — совместимые с напряжением 5 вольт.

 *   0 - Аналоговый ввод.
 *   1 - Вывод Push Pull на 10 МГц.
 *   2 - Вывод Push Pull на 2 МГц.
 *   3 - Вывод Push Pull на 50 МГц.
 *   4 - Цифровой вход.
 *   5 - Вывод Open Drain на 10 МГц.
 *   6 - Вывод Open Drain на 2 МГц.
 *   7 - Вывод Open Drain на 50 МГц.
 *   8 - Цифровой вход с подтяжкой в зависимости от значения в ODR.
 *   9 - Альтернативный вывод Push Pull на 10 МГц от периферии.
 *   A - Альтернативный вывод Push Pull на 2 МГц от периферии.
 *   B - Альтернативный вывод Push Pull на 50 МГц от периферии.
 *   C - Зарезервировано.
 *   D - Альтернативный вывод Open Drain на 10 МГц от периферии.
 *   E - Альтернативный вывод Open Drain на 2 МГц от периферии.
 *   F - Альтернативный вывод Open Drain на 50 МГц от периферии.

typedef enum Configuration
{
        PortAnalogIn = 0,
        PortIn = 0x04,
        PortPullUpOrDownIn = 0x08,
        PortOut = 0x03, // default Out is Out50Mhz
        PortOut10Mhz = 0x01,
        PortOut2Mhz = 0x02,
        PortOut50Mhz = 0x03,
        PortOpenDrainOut = 0x07,
        PortOpenDrainOut10Mhz = 0x05,
        PortOpenDrainOut2Mhz = 0x06,
        PortOpenDrainOut50Mhz = 0x07,
        PortAltOut = 0x0B,
        PortAltOut10Mhz = 0x09,
        PortAltOut2Mhz = 0x0A,
        PortAltOut50Mhz = 0x0B,
        PortAltOpenDrain = 0x0f,
        PortAltOpenDrain10Mhz = 0x0C,
        PortAltOpenDrain2Mhz = 0x0E,
        PortAltOpenDrain50Mhz = 0x0f
} port_configuration_t;



Запись и чтение GPIO

Для записи и чтения портов предназначены входной GPIOx_IDR и выходной GPIOx_ODR регистры данных.

Запись в выходной регистр ODR порта настроенного на вывод осуществляет установку выходных уровней всех разрядов порта в соответствии с записываемым значением. Если вывод настроен как вход с подтягивающими резисторами, состояние соответствующего бита регистра ODR активирует подтяжку вывода к шине питания (pull-up, ODR=1) или общей шине микроконтроллера (pull-down, ODR=0).

Чтение регистра IDR возвращает значение состояния выводов микроконтроллера настроенных как входы:

// Если кнопка нажата (PA0=1), установить биты порта C, иначе сбросить.
if (GPIOA->IDR & GPIO_IDR_IDR0) GPIOC->ODR=0xFFFF; else GPIOC->ODR=0x0000;

Сброс и установка битов порта

Для атомарного сброса и установки битов GPIO в микроконтроллерах STM32 предназначен регистр GPIOx_BSRR. Традиционный для архитектуры ARM способ управления битами регистров не требующий применения операции типа «чтение-модификация-запись” позволяет устанавливать и сбрасывать биты порта простой записью единицы в биты установки BS (BitSet) и сброса BR (BitReset) регистра BSRR. При этом запись в регистр нулевых битов не оказывает влияния на состояние соответствующих выводов.

GPIOx_BSRR – регистр сброса и установки битов порта:


GPIOC->BSRR=GPIO_BSRR_BS8|GPIO_BSRR_BR9; // Зажечь LED4 (PC8), погасить LED3.
GPIOC->BSRR=GPIO_BSRR_BS9|GPIO_BSRR_BR8; // Зажечь LED3 (PC9), погасить LED4.

Альтернативные функции GPIO и их переназначение (remapping)

Практически все внешние цепи специального назначения STM32 (включая выводы для подключения кварцевых резонаторов, JTAG/SWD и так далее) могут быть разрешены на соответствующих выводах микроконтроллера, либо отключены от них для возможности их использования в качестве выводов общего назначения. Выбор альтернативной функции вывода осуществляется при помощи регистров с префиксом «AFIO_”.

Помимо этого регистры AFIO_ позволяют выбирать несколько вариантов расположения специальных функций на выводах микроконтроллера. Это в частности относится к выводам коммуникационных интерфейсов, таймеров (регистры AFIO_MAPR), выводам внешних прерываний (регистры AFIO_EXTICR) и т. д.

суббота, 25 февраля 2012 г.

Assembler STM32F4 GPIO

Некоторые основные  команды ассемблера

Во-первых, загрузка большого числа (32 бита) в регистр.
LDR Rn, =число.

Rn — название регистра (R0, R1, ...), число — то, что хотим загрузить.
Например:
LDR R0, =0x40023830 ; Адрес регистра RCC_AHB1ENR

Для красоты и читабельности число можно заменить обозначением:
; Загрузим в регистр R0 адрес регистра RCC_AHB1ENR
LDR R0, =RCC_AHB1ENR

Обозначение должно быть объявлено в начале файла примерно так:
RCC_AHB1ENR EQU 0x40023830

Так можно обозвать любые константы и использовать их в коде.

Во-вторых, загрузка из памяти по заданному в регистре адресу.
LDR Rn, [Rm]

Rn — куда читаем,
Rm — адрес, откуда читаем.

Например, хотим прочитать, что записано в регистре RCC_AHB1ENR, адрес которого у нас хранится в регистре R0.
; Прочитаем в регистр R1 его содержимое
LDR R1, [R0]

Запись происходит аналогично, только команда называется STR:
; Запишем обратно
STR R1, [R0]

Между чтением и записью необходимо установить бит, отвечающий за тактирование порта D.
На помощь приходят команда логики OR.
ORR Rd, Ra, Rb
ORR Rd, Ra, #число

Rd — куда записывается результат;
Ra — первый операнд;
Rb — второй операнд;
число — вариант записи второго операнда прямо числом, если число удовлетворяет ряду требований (см. документацию).
Есть и иные варианты, но фиг с ними пока.

Пример: установка бита.
; Установим бит тактирования порта D
ORR R1, R1, #RCC_AHB1ENR_GPIODEN ; RCC_AHB1ENR_GPIODEN объявлен как 0x00000008, бит 3.

Точно так же записываются и ряд других логических и математических операций, список есть в мануале по ядру.
Зная это, уже можно настраивать периферию и даже моргать светодиодами. Но грузить каждый раз адрес регистра так не круто. Он лежит во флеше отдельно и ядру приходится делать лишний запрос.

Очень помогает в борьбе с этим косвенная адресация.
Типа как оператор -> в языке Си.

Записывается:
LDR Rn, [Rm, #смещение]
STR Rn, [Rm, #смещение]

То есть к адресу, записанном в Rm добавляется некоторое смещение прям вот так. Что удобно, смещение от базового адреса периферии для каждого регистра указано прямо в Referense Manual. Конечно, базовый адрес тоже указан.

Пример:
LDR R1, [R0, #GPIO_MODER_OFFSET] ; GPIO_MODER_OFFSET — смещение от базового адреса периферии GPIO до регистра MODER: 0x00000000

К слову, базовый адрес GPIOD: 0x40020C00. Все адреса можно подглядеть в даташите или Reference Manual.

Безусловный переход.
Бесконечный цикл делается с помощью этой команды. Выполнение продолжится с метки, указанной в аргументе:
B метка

Метка может располагаться как до команды, так и после неё.

Последнее, что требуется: задержка. Можно её оформить в виде отдельной процедуры.

Процедура оформляется так:
; Программная задержка
; R0 - величина задержки
delay PROC
; Какой-то полезный код
BX LR ; Возрат (типа return)
ENDP

BX LR — переход по адресу, записанному в регистре LR (R14). В этот регистр автоматически кладётся адрес команды, следующей за вызовом подпрограммы. Соответственно, эта команда осуществляет выход из процедуры.

Если есть вложенные процедуры, содержимое регистра надо сохранять, так как он перезаписывается автоматически при выполнении команд вызова подпрограммы вне зависимости от его содержания =) Но об этом потом.

Код задержки прост: принимаем число в регистре R0 и вычитаем его до тех пор, пока оно не станет 0.
; Вычитаем единицу
SUBS R0, R0, #1
; Пока не обнулилась, крутим дальше
BNE delay

Флаг S у процедуры SUB обозначает, что при выполнении команды будут выставлены флаги статуса, соответствующие результату выполнения. Ну, то есть, не ноль ли результат, было ли переполнение или заём и т.д.

Условный переход формируется из команды B и условного суффикса. Весь список можно посмотреть тут: Conditional execution.
В данном случае, выполняется проверка на «не ноль» (NE = Not Equal).

И последнее, вызов подпрограммы.
BL метка

метка — название подпрограммы. Пример:
BL delay

Именно команда перехода с суффиксом L сохраняет адрес следующей за ней команды в регистре LR.

Пример кода, моргающего светодиодами:

среда, 8 февраля 2012 г.

STM32F4 Discovery GPIO for C

// main.c

#include <stm32f4xx.h>

// Простая программная задержка
static void delay_cycles(uint32_t cycles)
{
    // Пока не вычтем до нуля, цикл не закончится
        while(cycles--);
}

// Здесь нельзя инициализировать глобальные переменные, не помеченные специально
// как не нуждающиеся в инициализации. Память инициализируется после вызова
// SystemInit и все значения будут затёрты.
//void SystemInit(void)
//{
//   // Пока тут ещё ничего нет.
//}

// Отсюда начинается выполнение пользовательского кода.
int main(void)
{
    // Светодиоды сидят на порту D и выводах 12 - 15.

    // Первым делом надо включить тактирование порту D.
    // За это отвечает 3 бит (GPIODEN) в регистре RCC_AHB1ENR (Reference manual, p.110)
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;

    // Дальше надо настроить выводы как выходы типа Push-pull, с максимальной частотой,
    // например, 50 МГц (от частоты зависит энергопотребление ножки).
 
    // Первый регистр, GPIOx_MODER: режим работы выхода, (RM, p. 148)
    // 2 бита на каждую ножку
    // 0: Вход, 1: выход, 2: альтернативная функция, 3: аналоговый
    GPIOD->MODER |= (1UL << 12 * 2) | (1UL << 13 * 2) | (1UL << 14 * 2) | (1UL << 15 * 2);
 
    // Второй регистр, GPIOx_OTYPER: тип выхода. Двухтактный (0) али открытый коллектор (1)
    // Один бит на каждую ножку. По умолчанию всё так, как и надо.
 
    // Третий регистр, GPIOx_OSPEEDR: максимальная скорость порта.
    // По умолчанию 2 МГц, так что ок.
 
    // Четвёртый регистр, GPIOx_PUPDR: куда он будет по умолчанию подтягивать, если выбран двухтактный режим.
    // 0: никуда, 1: питание, 2: земля, 3: резервировано. Два бита на вывод.
    // Допустим, к питанию.
    GPIOD->PUPDR |= (1UL << 12 * 2) | (1UL << 13 * 2) | (1UL << 14 * 2) | (1UL << 15 * 2);
 
    // Регистр вывода: GPIOx_ODR. Что запишешь, то на ножках и будет.
    // Есть регистр для установки битов и для их сброса (GPIOx_BSRR).
    // Младшие 2 байта отвечают за установку, старшие - за сброс.
 
    // Жги!
    GPIOD->BSRRL = (1UL << 12) | (1UL << 13) | (1UL << 14) | (1UL << 15);
    delay_cycles(1000000UL);
 
    // Утухни
    GPIOD->BSRRH = (1UL << 12) | (1UL << 13) | (1UL << 14) | (1UL << 15);
    delay_cycles(1000000UL);
 
    while(1)
    {
        // Зажжём 12й
        GPIOD->BSRRL = (1UL << 12);
     
                delay_cycles(1000000UL);
        // Погасим 12й
        GPIOD->BSRRH = (1UL << 12);
        // Зажжём 13й
        GPIOD->BSRRL = (1UL << 13);
     
                delay_cycles(1000000UL);
     
        // Погасим 13й
        GPIOD->BSRRH = (1UL << 13);
        // Зажжём 14й
        GPIOD->BSRRL = (1UL << 14);
     
                delay_cycles(1000000UL);
     
        // Погасим 14й
        GPIOD->BSRRH = (1UL << 14);
        // Зажжём 15й
        GPIOD->BSRRL = (1UL << 15);
     
                delay_cycles(1000000UL);
     
        // Погасим 15й
        GPIOD->BSRRH = (1UL << 15);
    }
}