INT 21h

Hi, I am Vladimir Smagin, SysAdmin and Kaptain. Telegram Email / GIT / RSS / GPG

Вольтметр на MSP430

№ 5298 В разделах: Electronics Programming от July 18th, 2013,
В подшивках:

В это действительно трудно поверить, но я все-таки нашел применение для пылящегося у меня MSP430G2231!

OLYMPUS DIGITAL CAMERA

Иногда у меня подозрительно попискивает инвертор 12-220 в машине. Чую в бортовой сети моей шнивочки завелись тараканы. Нужно как-то контроллировать напряжение. Начал ходить по магазинам и выяснил, что нужное мне устройство стоит не менее 350 рублей. Естественно, меня жаба задавила отдавать такие деньги когда цена ему 70-100 рублей.

Первым делом я загуглил возможно уже существующий такой проект и нашел его! В нем используется делитель напряжения, АЦП, индикатор, дешифратор и таймер. Лицом устройства будет конечно же индикатор, который, несомненно, должен быть красивым и ярким. Сначала я хотел взять индикаторы из старого проекта мотокомпьютера, но решил, что 4 мм высота цифр маловата для чтения во время управления автомобиля. Поэтому я не обломался и сходил в любимый магазин и купил какой-то советский 2 разрядный индикатор с готовым фильтром. Можете сравнить их ниже. Думаю, вы поймете мой выбор 🙂

OLYMPUS DIGITAL CAMERA 2013-07-18 20.58

Подключать ваш семисегментник надо через шифратор 74LS47. Поскольку его в России хрен найдешь, можно взять аналог 155ПП5 или 74HC4511. Последний стоит 18 руб. в местном магазине. Должно получиться что-то похожее как на фотке ниже, но только аккуратно.

OLYMPUS DIGITAL CAMERA

Ну а в качестве транзисторов вы просто обязаны взять КТ361. Отличить от КТ315 их можно по букве в центре, а не в углу слева.

OLYMPUS DIGITAL CAMERA

Схема устройства весьма проста. На ней сразу виден на входе микроконтроллера делитель, настраивающийся через 10 кОмный потенциометр, дешифратор и транзисторы для динамической развертки и питания индикаторов, которые являются импортными аналогами КТ361. Транзисторы питают индикаторы отдельно от МК, чтобы не создавать на нем излишнюю нагрузку. Не забываем про резисторы по 100 ом на каждой ноге индикатора. Хотя можете и как на картинке 56 ом, если не жалко индикатор.

msp430_voltmeter

Входное напряжение после делителя должно быть максимум 2.5 вольта, поэтому рекомендую сначала настроить ваш делитель, а потом подключать его. Примерное сопротивление потенциометра должно быть 7.45кОм. Можете сами посчитать на калькуляторе + узнаете как это делается 🙂 Дальше керамический конденсатор 0.1 мкф для удаления помех и в конце делителя диод Зенера на 2.7 вольта (он же стабилитрон). Стабилитрон при перенапряжении примет удар на себя и не даст сгореть микроконтроллеру.

V_divider

Перед тем как впаивать куда-то ваш микроконтроллер лучше сначала его прошить. Исходник для сборки можно взять тут. А сборка остального не должна у вас занять более получаса. Лично я вообще на весу все спаял и ни сколько об этом не сожалею, т.к. получилось очень компактно + залил все пластиком, который не даст чему-то сломаться.

Нет комментариев »

MSP430G2231 и таймер

№ 2977 В разделах: Electronics Programming от June 15th, 2011,
В подшивках:

Это очень простой пример работы с таймером. Уверен, вы найдете ему более полезные применения. Давайте припаяем часовой кварц (32768 Гц) к микроконтроллеру и сделаем тестовую программу.

#include "msp430g2231.h"

#define DIOD 6 //диод на ноге P1.6

unsigned int timerCount = 0;

#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0 (void) {
  timerCount = (timerCount + 1) % 8;
  if(timerCount ==0) {
  P1OUT &= ~(1 << DIOD);
  for(double i=0; i < 500 ; i++);
  P1OUT |= 1 << DIOD;  }
}

int main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  //Initialize pins
  P1DIR |= 0xFF;
  
  //timer (oh, shit)
  TACCTL0 = CCIE;
  TACTL = TASSEL_2 | MC_2;

  __enable_interrupt();

  __bis_SR_register(LPM0 + GIE); /// LPM0  прерываниями
}

В итоге мы получим вот такую классную мигающую штуку. Зеленый светодиод на плате это и есть тот, которым мы мигаем.

Всего 1 комментарий »

Управление 7-сегментным индикатором, динамическая развертка, MSP430G2231 (MSP430) и регистр 74HC595

№ 2965 В разделах: Electronics Programming от June 12th, 2011,
В подшивках: ,

?Я все не перестаю баловаться отладочной платкой MSP-EXP430G2 Launchpad, задаренной мне ZiB’ом (за что ему, кстати, огромное спасибо. я приобрел много опыта на ней).

Теорию и схему рекомендую прочитать в статье, общей для всех микроконтроллеров про вывод чисел на 7-сегментные индикаторы.

Способ первый и самый простой

В данном примере возможно выводить хоть и на все 3 цифры на индикаторе, но все равно одну и туже информацию. Подключение очень простое: через резисторы по 1 кОм подключены напрямую к всем 8 выводам микроконтроллера. Общий анод подключен к +3.5 на плате.

Этот способ не очень примечателен, т.к. малофункционален и забирает под себя все свободные пины у микроконтроллера, но ярко показывает принцип работы с такими индикаторами.

А вот и мой говнокод:

#include "io430.h"

void show(int num, int duration) {
    unsigned char digits[]=
      {
        0xF7,
        0xC4,
        0x6B,
        0xEE,
        0xDC,
        0xBE,
        0xBF,
        0xE4,
        0xFF,
        0xFE
      };
    P1OUT ^= digits[num];
    for(double i=0; i <duration ; i++);
    P1OUT ^= digits[num];
}

int main( void )
{
  //Останавливаем watchdog
  WDTCTL = WDTPW + WDTHOLD;
  //Включаем вывод на пинах микроконтроллера
  P1DIR |= 0xFF;
  int n=0;
  for(;;) {
    show(n,1000);
    n++;
    if (n==10) n=0;
  }
  return 0;
}

Обратите внимание, что код неполный, т.к. подключен всего один индикатор из трех.

Теперь подключим сдвиговый регистр 74HC595

Здесь подключение индикатора к регистру также не выделяется ничем примечательным – пины данных индикатора подключаются к 8 выводам для данных на регистре. Сам регистр подключается к МК к любым выбранным вам выводам (я выбрал 0, 1, 2, 3). Итого имеем 4 ноги от регистра к МК для управления регистром и 3 ноги от общих анодов к остальным 3 выводам МК (остается еще 1 пин на МК, на который можно что-нибудь подключить, но об этом попозже).

Вначале все было хорошо, но меня огорчала проблема с точкой возле самой первой выводимой цифры, которая появлялась всего 1 раз при включении устройства. Конечно, я делал сброс регистра перед его использованием, но, как оказалось, помимо импульса защелки надо слать перед этим еще и 1 тактовый импульс.

#include "msp430g2231.h"

//ноги МК к которым подключен сдвиговый регистр
#define REG_MR 3
#define REG_SHCP 0
#define REG_STCP 1
#define REG_DS 2

//три цифры на индикаторе соединены с другими 3 ногами на МК
#define IND1 4
#define IND2 5
#define IND3 7

void show(int num) {
    int num_ = num;
    static unsigned char digits[]=
    {
       0x88, //0
       0xBB, //1
       0x94, //2
       0x91, //3
       0xA3, //4
       0xC1, //5
       0xC0, //6
       0x9B, //7
       0x80, //8
       0x81  //9
    };       
    unsigned char value;
   
    value = digits[num];
    
    for(int i = 8; i; --i)
    {
        if(value & 0x80)
            P1OUT |= 1<<REG_DS; //1
        else
            P1OUT &= ~(1<<REG_DS); //0
        P1OUT |= 1<<REG_SHCP;
        P1OUT &= ~(1<<REG_SHCP);
        value <<= 1;
    }
    P1OUT &= ~(1<<REG_DS);
    P1OUT |= 1<<REG_STCP;
    P1OUT &= ~(1<<REG_STCP);
    P1OUT |= 1<<REG_STCP;
}

int main( void )
{
  //Выключаем watchdog
  WDTCTL = WDTPW + WDTHOLD;

  //Настраиваем порт МК для вывода
  P1DIR |= 0xFF;
 
  //Инициализируем регистр и включаем только первую цифру на индикаторе 
  P1OUT |= (1<<REG_MR)|(1<<REG_SHCP)|(1<<REG_STCP)|(1<<REG_DS);
  P1OUT &= ~(1<<IND1);
  P1OUT &= ~(1<<IND2);
  P1OUT &= ~(1<<IND3);
  P1OUT |= (1<<IND1);
  
  //Сбрасываем регистр
  P1OUT |= 1<<REG_STCP;
  P1OUT &= ~(1<<REG_MR); //включаем ногу сброса регистра
  P1OUT |= 1<<REG_SHCP; //ГРАБЛИ! ВЫДАТЬ ТАКТ ОБЯЗАТЕЛЬНО!
  P1OUT &= ~(1<<REG_SHCP);
  P1OUT &= ~(1<<REG_STCP); //ДЕРГАЕМ ЗАЩЕЛКУ!
  P1OUT |= 1<<REG_STCP;  
  P1OUT |= 1<<REG_MR; //выключаем сброс
  //а тут мы выводим циклом цифры от 0 до 9
  int n=0;
  for(;;) {
    show(n);
    n++;
    if (n==10) n=0;
    //небольшая пауза. знаю, что правильней таймером
    //попозже используем и его
    for(double i=0; i <3000 ; i++); 
  }
  return 0;  
}

А теперь применим динамическую развертку с таймерами, прерываниями, блэкджеком и шлюхами

#include "msp430g2231.h"

#define REG_MR 3
#define REG_SHCP 0
#define REG_STCP 1
#define REG_DS 2

#define IND1 4
#define IND2 5
#define IND3 7

unsigned int C0=0, C1=0, C2=0; //индексы для массива знаков

void get_indexes(int num) {
	//вывод обычного натурального числа (беззнаковое, целое)	
        int C0_=0, C1_=0, C2_=0; //это нужно чтобы переменная записалась в 
        //глобальные только после обсчета, а не во время его
	while(num > 0) {
		//отнимаем тысячи
		if (num > 100) {
			num = num - 100;
			C0_++;
		} else {
			//отнимаем сотни
			if (num > 10) {			
				num = num - 10;
				C1_++;
			} else {			
				//отнимаем десятки
				if (num >= 1) {
					num = num - 1;
					C2_++;
                                        
				} 
                                if (C2_ > 9) { C2_=0; C1_++;}
			}
                        if (C1_ > 9) { C1_=0; C0_++; }
		}
                if (C0_ > 9) { C0_=0; }
  	}
        
        C0=C0_; C1=C1_; C2=C2_;
 
	//если первая цифра 0, то не зажигаем ничего. последний 0 будет показываться!
	//if (C0 == 0) { C0=11; }
	//if ((C0 + C1) == 0)  { C0=C1=11; }
	//if ((C0 + C1 + C2) == 0)  { C0=C1=C2=11; }
 
}

void show_symbol(int index) {
    static unsigned char digits[]=
    {
       0x88, //0
       0xBB, //1
       0x94, //2
       0x91, //3
       0xA3, //4
       0xC1, //5
       0xC0, //6
       0x9B, //7
       0x80, //8
       0x81, //9
       0xFF  //пусто
    };

    unsigned char value;
    
    value = digits[index];
    
    for(int i = 8; i; --i)
    {
        if(value & 0x80)
            P1OUT |= 1<<REG_DS; //1
        else
            P1OUT &= ~(1<<REG_DS); //0
        P1OUT |= 1<<REG_SHCP;
        P1OUT &= ~(1<<REG_SHCP);
        value <<= 1;
    }
    P1OUT &= ~(1<<REG_DS);
    P1OUT |= 1<<REG_STCP;
    P1OUT &= ~(1<<REG_STCP);
    P1OUT |= 1<<REG_STCP;
    
}



int main( void )
{
  // Останавливаем watchdog
  WDTCTL = WDTPW + WDTHOLD;

  //Инициализируем порт МК
  P1DIR |= 0xFF;
  
  //Настраиваем таймер
  CCTL0 = CCIE;
  CCR0 = 300;
  TACTL = TASSEL_1 + MC_1;
  
  __enable_interrupt();
  
  P1OUT |= (1<<REG_MR)|(1<<REG_SHCP)|(1<<REG_STCP)|(1<<REG_DS);
  P1OUT &= ~(1<<IND1);
  P1OUT &= ~(1<<IND2);
  P1OUT &= ~(1<<IND3);
  
  //Сбрасываем сдвиговый регистр
  P1OUT |= 1<<REG_STCP;
  P1OUT &= ~(1<<REG_MR);
  P1OUT |= 1<<REG_SHCP;
  P1OUT &= ~(1<<REG_SHCP);
  P1OUT &= ~(1<<REG_STCP);
  P1OUT |= 1<<REG_STCP;  
  P1OUT |= 1<<REG_MR;
  
  int n=0;
  for(;;) {
    get_indexes(n);
    n++;
    if (n==129) n=0;
    for(double i=0; i <150 ; i++);
  }
  return 0;
  
  
}

//Обработка таймера

#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0 (void) {
    // 1
    show_symbol(C2);
    P1OUT |= (1<<IND1);
    for(double i=0; i <15 ; i++);
    P1OUT &= ~(1<<IND1);

    // 2
    show_symbol(C1);
    P1OUT |= (1<<IND2);    
    for(double i=0; i <15 ; i++);    
    P1OUT &= ~(1<<IND2);
    
    // 3
    show_symbol(C0);
    P1OUT |= (1<<IND3);    
    for(double i=0; i <15 ; i++);  
    P1OUT &= ~(1<<IND3);
}

17 комментариев »

Эксперименты с Texas Instruments MSP-EXP430G2 Launchpad

№ 2945 В разделах: Electronics Programming от June 8th, 2011,
В подшивках:

#include "io430.h"

void delay( double delay ) {
  for(int i=0; i < delay ; i++);
}

void sound( int ton, int msec ) {
    
  int ton_;
  double msec_;
    
  msec_ = floor(msec / ton) * 10;
    
    do { 
      //MSEC
      msec_--;
      ton_ = ton;
      //TON
      do ton_--;
      while (ton_ > 0);  
      
      //BEEP
      P1OUT ^= 0x40;
      
    } while (msec_ > 0);  
    
}

int main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  P1DIR |= 0x40;
  P1DIR |= 0x01;
  for (;;)
  {
    sound(100,6000);
    sound(200,6000);
    sound(100,6000);
    sound(200,6000);
    sound(70,6000);
    sound(80,6000);
    sound(90,6000);
    delay(9000);

  }

}

Нет комментариев »

Яндекс.Метрика

Fortune cookie: Confucious say: woman who goes to man's apartment for snack, may get tit bit.