STM8L051F3: режимы GPIO, тактирование, энергопотребление

разделы: STM8 , дата: 23 апреля 2016г.

В этот раз разберемся с портами I/O, научимся управлять рабочей частотой чипа и измерим потребление тока в Active режиме.

Я буду использовать режимы работы GPIO в AVR в качестве переводчика, для понимания терминологии SMT8.

Управление GPIO в STM8 похоже на AVR, но, как бы сказать, более логично с точки зрения здравого смысла. Однако, что бы разобраться с режимами GPIO в STM8 придется выучить новый термин: Open Drain. Замечу, что ничего нового в этом термине нет для освоивших GPIO в AVR.

Итак, в AVR портом GPIO можно было управлять двумя регистрами I/O: DDRx и PORTx; Третий регистр - PINx, был доступен только для чтения, и он ничем не управлял.

В STM8 для управления портом GPIO служат уже три регистра: Px_DDR, Px_ODR, Px_CR1. Регистр Px_IDR аналогичен PINx - он ничем не управляет. Регистр Px_CR2 служит для установки прерывания и режима тактирования GPIO, к нашей теме отношение тоже не имеет

Если в AVR только DDRx определял режим работы PORTx, то в STM8 для этого служат Px_DDR и Px_CR1, причем второй в Open Drain режиме имеет приоритет над первым.

    Как не сложно подсчитать, три регистра дают комбинацию из 8 состояний GPIO:
  • Выход Push-pull или PP: (CR1=1 && DDR=1) => тогда состояние ODR задает режим GPIO. При логической единице порт подключен к шине питания, иначе - к земле.
  • Вход Pull-up или точнее  WPU(weak pull-up) (CR1=1 && DDR=0)  значение ODR в этом состоянии ни на что не влияет. Соответствующий пин порта можно напрямую замыкать на землю, Проходящий ток у меня составил 88 мкА. Слабовато, да.
  • Вход Floating или HiZ или высокоимпедансный вход. (CR1=0 && DDR=0). Здесь все ясно, думаю. Это не плюс и не минус. Значение ODR в этом состоянии также ни на что не влияет.
  • Выход. Open Drain или OD. (СR1=0 && DDR=1) Последний режим GPIO сочетает в себе режимы: вход Floating(HiZ) и выход Push-Pull. При ODR=1, порт переключается в floating/HiZ режим, при ODR=0 подключается с земле.

Последний Open Drain, или вернее, pseudo Open Drain - специальный режим для работы с последовательной шиной (различные вариаций I2C, 1Wire и т.д.). В AVR он создавался записью нуля в PORTx и переключался изменением DDRx. Такой способ приводил к инверсионной логике (запись логической единицы в DDR подключала к земле). В STM8 такой жести нет! Ноль это ноль, а единица это "отпускание шины" до логической единицы.

Тактирование

С режимами GPIO разобрались, осталось разобраться с энергопотреблением. STM8L это линейка микроконтроллеров для батарейного питания. По идее такой микроконтроллер должен мало потреблять. Но когда запускаем L051 чип с пустой программой, получаем ток потребления 900мкн. Не слабо!

Но, это смотря с чем сравнивать. Если сравнивать с ATtiny13A, то сперва нужно опустить частоту тактового генератора до 1 МГц.

Так же как и AVR, STM8 имеет два генератора частоты. Основной - HSI и тихоходный LSI от которого тактируется watchdog. Основной генератор работает на частоте 16МГц и для тактирования основной шины использует делитель в регистре CLK_CKDIVR:

По умолчанию делитель равен 8, т.е. чип стартует на 2МГц.Пробуем изменить делитель на 16:

/* homepage: www.count-zero.ru/stm8/
 * hard&soft: SDCC && stm8flash && stm8l051f3p6
 * compile:  sdcc -mstm8 -DSTM8L051 ./code.c
 * download to chip: # stm8flash -c stlinkv2 -p stm8l051f3 -w ./code.ihx
 *
 */
#define CLK_CKDIVR *(unsigned char*)0x50C0

#define PA_ODR *(unsigned char*)0x5000
#define PA_DDR *(unsigned char*)0x5002
#define PA_CR1 *(unsigned char*)0x5003

#define PB_ODR *(unsigned char*)0x5005
#define PB_DDR *(unsigned char*)0x5007
#define PB_CR1 *(unsigned char*)0x5008

#define PC_ODR *(unsigned char*)0x500A
#define PC_DDR *(unsigned char*)0x500C
#define PC_CR1 *(unsigned char*)0x500D

#define PD_ODR *(unsigned char*)0x500F
#define PD_DDR *(unsigned char*)0x5011
#define PD_CR1 *(unsigned char*)0x5012

#define P7 7
#define P6 6
#define P5 5
#define P4 4
#define P3 3
#define P2 2
#define P1 1
#define P0 0

int k=0;

static void delay(unsigned int t)
{
  while(t--);
}

int main( void )
{
  PB_DDR|=(1<<P5);
  PB_CR1|=(1<<P5);


   for(;;){

      PB_ODR ^= (1<<P5);

      delay(60000);
  if (k == 10)
   CLK_CKDIVR=4; //set prescaler = 16
      delay(60000);
  k++;
   }
}

Уменьшение частоты можно визуально наблюдать по увеличившемуся периоду мигания светодиода. Потребление тока падает с 900 до 725 мкА. Все равно как-то многовато :(

Теперь попробуем такую фишку. Вся сложная периферия в stm8l отключена по умолчанию. Но GPIO, находящиеся по умолчанию в HiZ режиме, могут немало наматывать. Попробуем их отключить:

/* homepage: www.count-zero.ru/stm8/
 * hard&soft: SDCC && stm8flash && stm8l051f3p6
 * compile:  sdcc -mstm8 -DSTM8L051 ./code.c
 * download to chip: # stm8flash -c stlinkv2 -p stm8l051f3 -w ./code.ihx
 *
 */

#define CLK_CKDIVR *(unsigned char*)0x50C0

#define PA_ODR *(unsigned char*)0x5000
#define PA_DDR *(unsigned char*)0x5002
#define PA_CR1 *(unsigned char*)0x5003

#define PB_ODR *(unsigned char*)0x5005
#define PB_DDR *(unsigned char*)0x5007
#define PB_CR1 *(unsigned char*)0x5008

#define PC_ODR *(unsigned char*)0x500A
#define PC_DDR *(unsigned char*)0x500C
#define PC_CR1 *(unsigned char*)0x500D

#define PD_ODR *(unsigned char*)0x500F
#define PD_DDR *(unsigned char*)0x5011
#define PD_CR1 *(unsigned char*)0x5012

#define P7 7
#define P6 6
#define P5 5
#define P4 4
#define P3 3
#define P2 2
#define P1 1
#define P0 0

int k=0;

static void delay(unsigned int t)
{
  while(t--);
}

int main( void )
{

 // to ground Port A
 PA_DDR = 0xFF;
 PA_CR1 = 0xFF;
 PA_ODR = 0;

 // to ground Port B
 PB_DDR = 0xFF;
 PB_CR1 = 0xFF;
 PB_ODR = 0;

 // to ground Port C
 PC_DDR = 0xFF;
 PC_CR1 = 0xFF;
 PC_ODR = 0;

 // to ground Port D
 PD_DDR = 0xFF;
 PD_CR1 = 0xFF;
 PD_ODR = 0;

   for(;;){
      PB_ODR ^= (1<<P5);

      delay(60000);
  if (k == 10)
   CLK_CKDIVR=4; //set prescaler = 16
  k++;
      delay(60000);
   }
}

В результате такой нехитрой манипуляции имеем 575 мкА. Это немного больше, чем ATtiny13A c 525мкА, и больше, чем MSP430G2453 с 335мкА, но и чип более богат периферией. Теперь попробуем снизить частоту до 128  кГц, выставив делитель в значение 7, и... потребление упало до 298 мкА!

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

поделиться: