'Practice & Training/MSP430 MicroController'에 해당되는 글 3건

  1. 2013.12.02 MSP430 ADC Linear Check
  2. 2013.12.02 MSP430 Information Layer
  3. 2013.07.01 MSP430 IAR Start - Create New Project

MSP430AFE253은 시그마-델타(SD) 방식의 아날로그 디지털 컨버터(ADC) 3채널이 내장되어 있어 학생들에[겐 조금은 특이하게 느껴  질 수 있는 마이크로컨트로러(MCU)입니다. 하지만 개발을 하는 회사 입장에선 고가의 ADC 전용 칩을 저가의 MCU($1 이하)와 소프트웨어 기술로 대체가 가능하다는 점에서 관심을 가질 수 밖에 없는 제품입니다.

그러다 보니 해당 제품을 사용하는 회사들이 생각보다 많고 저 역시 이 제품으로 개발을 하게 되었습니다. 그런데 주먹구구식으로 한참 개발하다 보니 교정기에서 나오는 전압을 선형적으로 받아 들이지 못한다는 느낌을 받게 되었습니다. 여기서 선형적이다라는 말은 0mV 부터 750mV 까지 1mV식 증가 시킬 때 ADC의 결과가 일정하게 증가하느냐 말합니다. 그런데 제가 구성한 회로에선 일정하게 증가하지 않고 특정 구간에서 너무 많은 차이를 보이면서 증가를 하더군요. 그래서 다음과 같은 실험을 하게 되었습니다.




실험환경은 다음과 같습니다.



1. 교정기는 YOGOKAYA사의 CA100을 가지고 하였습니다.

2. MSP430AFE253의 CH0을 이용하여 측정을 하였습니다.

3. Vref는 TI 사의 TLVH431을 이용하여 1.5V를 구성하였습니다.

4. 저항은 가급적 정밀급인 D급을 사용하였습니다.(일부 F급 존재)

5. 직접 설계한 SMD PCB 상에서 측정하였습니다.

6. 위 회로의 R을 바꿔가며 측정을 하였습니다.




실험 결과는 다음의 구글 스프레드시트로 정리가 되어 있습니다.

https://docs.google.com/spreadsheet/ccc?key=0Ahy59sLNIHx3dFl6aU84WmdaSzQ0RTkySFJKb0dxanc


실험 결과을 한 결과 다음과 같이 정리를 할 수 있었습니다.


1. MSP430AFE253 추세 선형성




2. MSP430AFE253 차동 선형성




그리고 마지막으로 위의 시스템에서 R을 제거 하고 바로 전압을 인가 하였을 때의 결과 입니다.







제가 전기전자 회로 이론을 잘 아는 것이 아니라서 이론적으로는 말씀 들릴 수는 없습니다. 하지만, 하루정도를 허비해서 실험한 결과를 정리하면 다음과 같습니다.

1. R을 100Kohm으로 바꾸면 위의 차동 선형성 그래프처럼 골짜기 형상이 나타나는 것이라 아니라 Z형 그래프를 그리게 됩니다.

2. R을 10Kohm부터 560ohm 까지 해보면서 저항값이 작아 질수록 자동 선형성 그래프가 좋아 짐을 확인 할 수 있습니다.

이는옴의 법칙인 전압=전류*저항(V=I*R)을 바탕으로 단순하게 생각을 해본다면, V와 R을 실험에서의 고정시켜서 관찰한 결 결과이므로 MCU의 ADC의 입력 전류가 일정 이하로 떨어지게 되면 이것이 ADC 결과에 영향을 미치는 것이라고 결론을 내릴 수 밖에 없다고 생각합니다.

이부분에 대해선 제가 마이크로프로세서를 가지고 먹고 살고 있지만 지식이 미천하여 더 이상의 상세한 설명은 불가능 하므로 추후 해당 문제에 대해서 알게 되면 다시 정리 하도록 하겠습니다.

 


회로 수정하면서 OPAMP로 버퍼 회로를 구성하여 테스트 한 결과 기존의 있던 비 선형성은 줄어 들게 되었습니다. 다만 OPAMP가 계측용이 아니라서 오차가 발생하는 데다, Zero Shift가 발생되면서, 또 다른 문제를 야기하게 되었습니다. 아무튼 이 테스트로 알수 있게 된 것은 MSP430AFE253의 ADC에 버퍼가 없음으로 인해서 발생한 문제로 여겨 집니다. 만약 해당 MCU를 사용하신다면 외부에 버퍼 회로를 구성하여 사용하시는 것을 고려 하시거나 경쟁사인 ADI의 ADuM36x 시리즈(ADuM360, ADuM361)를 이용하는 것을 고려해 볼만 하다고 여겨집니다.

Posted by klisty
,

제품을 만들다 보면 어떻한 데이터를 저장해야 하는 경우가 발생합니다. 가령 제품이 전원이 꺼지기 전의 상태를 기억해야 하거나, 제품이 정확한 값을 출력 시키기 위해서 교정한 데이터를 기억하여 활용하는 상황이 발생하게 됩니다. 이런 경우 데이터의 저장 빈도나 제품의 목적 및 활용성에 따라 다양한 방법으로 데이터를 저장하게 됩니다. 일반적인 소규모의 임베디드 제품에선 저장해야 하는 데이터의 양도 적을 뿐더러 저장 빈도도 적기 때문에 주로 MCU 내부에 존재하는 저장 장소를 이용합니다. 하지만 모바일 제품으로 갈수록 저장 빈도도 많아지고 데이터의 크기도 많기 때문에 MCU 외부에 존재하는 저장 장솔르 이용합니다. 가령 저장량은 작지만 저장빈도가 높을 경우는 외부의 EEPROM 같은 걸 사용하고 용량이 커질수록 Flash 로 넘어 가게 됩니다.

하지만 우리가 지금 언급하려는 TI의 MSP430AFE253는 소규모 임베디드 시스템에 적용하는 MCU이면서 내부에 EEPROM 같은 별도의 저장 공간이 들어 있지 않습니다. 그러다 보니 TI에선 다른 방법을 활용하여 EEPROM 같은 기능을 제공하게 됩니다.

 

그렇다면 어떻게 하느냐? 여러 방법들이 존재 하겠지만 TI의 경우는 MCU의 프로그램이 구동되는 Flash 영역 일부를 특정 영역으로 지정하여 이 부분에는 사용자가 임으로 데이터를 기록 할 수 있도록 하였습니다. 그런데 Datasheet에서 이 부분을 언급하는 part에선 TI에서 지정한 영역 이외에도 프로그램이 하다고 설명을 합니다. 자세히 읽어 보면 이게 바로 일종의 bootloader를 만들 때 참고해야 할 부분으로 보여 집니다. 

아무튼, 지금 언급하려는 것은 그런 부분이 아니니 넘기겠습니다.

 

그렇다면 지금까지 설명한 부분이 무엇이냐?! 하시겠죠. 그부분이 바로 제목에서 보셨듯이 Information Layer 입니다. Information Layer의 설명은 MSP430 User's Guide 의 Flash Memory Controller에 존재합니다.(여기서 설명할 MCU는 MSP430AFE253을 기준으로 설명해 드리고 있으며 해당 문서의 번호는 SLAU144H 입니다.) Flash Memory Controller는 bit, byte, word 단위로 Address 접근과 프로그램이 가능합니다. 물론 MSP430의 Flash Memory Controller은 많은 장점을 가지고 있으나 지금 궁금한것은 이것이 아니니 넘기도록 하겠습니다.


MSP의 Flash Memory는 Information Layer 라는 부분을 따로 때어 놓았을 때부터 알아 보셨듯이 하나의 Flash Memory를 자잘하게 나누어 놓았습니다. 다음과 같이 크게 Flash Main Memory와 Flash Information Memory로 구분됨을 보실수 있으실 것입니다.



일단은 User's Guide에 있는 32KByte로 예로 들었습니다만, Flash Memory는 Segment로 구분이 되고 세그 먼트는 다시 Block으로 구분이 됨을 알 수 있습니다. 여기서 Information Layer은 Block 단위로는 지울수 없고, 오직 Segment 단위로만 삭제가 가능합니다. 그리고 Main Memory의 Block의 크기는 64byte이고 Segment의 크기는 256byte입니다.

Infomation Layer의 Segment 크기는 64byte인데 이것이 최소 삭제 가능 메모리의 크기입니다. 이것이 나타내는 다른 의미는 Segment A의 내용을 수정하기 위해선 최소한 64byte의 ram이 필요합니다. 이런 이유는 MSP430의 Flash Memory 동작 특성 때문에 쓰기는 Byte 나 Word 단위로 가능하지만 삭제는 최소 Block이나 Segment 단위로 가능하기 때문입니다. 이런 동작 특성은 프로그램을 작성할 때 Information Layer 수정시 반드시 읽기 먼저 수행하고 이후에 쓰기를 실시하게 하는 이유가 됩니다.


그렇다면 Information Layer에 프로그램을 작성하기 위해선 어떻게 해야 할까요? 여기에 대해선 TI가 참 친절하게도 Example Source을 제공하고 있습니다. 특별하게 Basic Clock Module를 변경하지 않으셨다면 다음의 예제를 참고 하시면 됩니다.



[MSP430AFE_FLASHWRITE_01‎‎‎‎]


#include <msp430afe253.h>


char value;  // 8-bit value to write to seg C


// Function prototypes

void write_SegC(char value);

void copy_C2D(void);


void main(void)

{

    WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer


    FCTL2 = FWKEY + FSSEL0 + FN1;             // MCLK/3 for Flash Timing Generator

    value = 0;                                // initialize value


    while(1)                                  // Repeat forever

    {

        write_SegC(value++);                    // Write segment C, increment value

        copy_C2D();                             // Copy segment C to D

        __no_operation();                       // SET BREAKPOINT HERE

    }

}


void write_SegC(char value)

{

    char *Flash_ptr;                          // Flash pointer

    unsigned int i;


    Flash_ptr = (char *)0x1040;               // Initialize Flash pointer

    FCTL3 = FWKEY;                            // Clear Lock bit

    FCTL1 = FWKEY + ERASE;                    // Set Erase bit

    *Flash_ptr = 0;                           // Dummy write to erase Flash seg


    FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation


    for (i = 0; i < 64; i++)

    {

        *Flash_ptr++ = value;                   // Write value to flash

    }


    FCTL1 = FWKEY;                            // Clear WRT bit

    FCTL3 = FWKEY + LOCK;                     // Set LOCK bit

}


void copy_C2D(void)

{

    char *Flash_ptrC;                         // Segment C pointer

    char *Flash_ptrD;                         // Segment D pointer

    unsigned int i;


    Flash_ptrC = (char *)0x1040;              // Initialize Flash segment C ptr

    Flash_ptrD = (char *)0x1000;              // Initialize Flash segment D ptr

    FCTL3 = FWKEY;                            // Clear Lock bit

    FCTL1 = FWKEY + ERASE;                    // Set Erase bit

    *Flash_ptrD = 0;                          // Dummy write to erase Flash seg D

    FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation


    for (i = 0; i < 64; i++)

    {

        *Flash_ptrD++ = *Flash_ptrC++;          // copy value segment C to seg D

    }


    FCTL1 = FWKEY;                            // Clear WRT bit

    FCTL3 = FWKEY + LOCK;                     // Set LOCK bit

}



하지만 만약 외부 클럭을 받거나 내부 클럭을 변경하였다면 그에 따라 설정도 바뀌게 되고, 이러한 클럭 변화는 당연하게도 MCU 전반에 영향을 미치게 됩니다. 이는 Flash Memory(Information Layer)도 예외는 아닙니다. 따라서 위와 같은 기본 예제의 소스를 활용해선 답이 나오지 않습니다. 그렇다면 어떻게 해야 하느냐? 이는 다시 User's Guide를 확인해 봐야 합니다. 일단 여기선 Basic Clock Module에 대한 설명은 제외 하도록 하겠습니다. User's Guide에 보면 'Initiating an Erase from Within Flash Memory', 'Initiating an Erase from RAM', 'Initiating a Byte/Word Write from Within Flash Memory', 'Initiating a Byte/Word Write from RAM', 'Block Write Flow and Example' 라는 항목이 존재합니다. 여기에 보면 바로 Flow-Chart가 나오는데, 이에 맞추어서 프로그램을 작성하시면 됩니다.
 
우선 Information Layer를 초기화 하기 위해선 Basic Clock Module의 영향을 어떻게 받았는지 알아야 합니다. 이는 FCTL2 레지스터의 설정이 변경됨을 의미합니다. 역시서 우리가 변경해야 할 것은 FNx의 부분인 5~0번 bit들 입니다. 그렇다면 어떻게 설정을 하느냐? 생각보다 간단합니다. User's Guide의 Flash Memory Timing Generator부분을 보면 256K <= f-FTG <=477가 되도록 FNx를 수정하라고 합니다. 만약 사용하는 Basic Clock이 MCLK(또는 SMCLK) = 14.745MHz 이고 FN을 36으로 설정한다고 한다면 그 값은 MCLK / (FNx + 1) 이므로 398.5153가 됩니다. 즉 f-FTG 범위내에 들어 가는 것이죠. 아무튼 다음의 공식에 따라 FNx를 구하시면 됩니다. [ FNx = (S)MCLK / f-FTG - 1 ]
 
그 다음으론 'Initiating an Erase from Within Flash Memory', 'Initiating an Erase from RAM', 'Initiating a Byte/Word Write from Within Flash Memory', 'Initiating a Byte/Word Write from RAM', 'Block Write Flow and Example' 등 다양한 것들이 있지만 사실 이것들은 어떻게 보면 'Block Write Flow and Example'의 일부분이라고 볼 수 있기에 이 부분만 설명 하도록 하겠습니다.
'Block Write Flow and Example'의 Flow-Chart는 다음과 같습니다.




여기서 중요한 것은 바로 Flash Memory Controller가 충분하게 Flash에 data를 기록할 수 있는 시간을 주는 것입니다. 만약 가장 기본적인 클럭(MSP430AFE253은 Basic Clock Module이 1MHz이다.)보다 낮으면 상관 없지만 만약 높다면 Debuger 상에선 Information Layer에 기록 된 것처럼 보이지만 리셋지 해당 영역이 초기화 되거나 엉뚱한 값이 저장되어 있는 것을 보실 수가 있습니다. 따라서 위의 Flow-Chart에서 BUSY와 WAIT를 명심하셔서 삽입하셔야 합니다. 이는 MSP430의 Information Layer 뿐만 아니라 SRAM, EEPROM 등도 마찬가지입니다. 해당 모듈들이 기존의 작업을 완료하지 못한 상태인데 외부에서 접근을 시도하게 되면 해당 접근 번지나 이전 접근 번지엔 원하지 않는 필요없는 데이터가 기록되게 됩니다.

이러한 BUSY와 WAIT를 고려하여 프로그램을 수정하게 되면 다음과 같습니다.



[MSP430AFE_FLASHWRITE_02‎]


//****************************************************************//

//                                                                //

//           MSP430 : Flash Memory (Informaion Area)              //

//                                                                //

//****************************************************************//



#define FLASH_WRITE_ENABLE     (1)

#define FLASH_SIZE             (0x30)


#define FLASH_FRKEY            (0x9600)  // FRKEY

#define FLASH_FWKEY            (0xA500)  // FWKEY


// FCTL3, This bit indicates the status of the flash timing generator

#define FlashBusy() (FCTL3 & BUSY == BUSY) ? true : false

// FCTL3, Indicates the flash memory is being written to.

#define FlashWait() (FCTL3 & WAIT == WAIT) ? true : false



unsigned char flash[FLASH_SIZE];



// Interrupt enable

void IntGlobal(bool bConfig){

    // Interrupt enable (power mode : normal)

    if( bConfig ) _EINT();

    // Interrupt disable (power mode : normal)

    else          _DINT();

}    




void FlashConfigSet(void){

    while( FlashBusy() );

    FCTL2 = FWKEY + FSSEL0 + FN5 + FN2;   MCLK/3 for Flash Timing Generator

    FCTL1 = FWKEY;

    FCTL3 = FWKEY;

}



void FlashPutEnable(void){

    unsigned char* address = (unsigned char *)0x1000;  

    

    while( FlashBusy() );  // Busy check

    FCTL3 = FLASH_FWKEY;  // Clear Lock bit

    FCTL1 = FLASH_FWKEY | ERASE;  // Set Erase bit

}

void FlashPutDisable(void){

    FCTL1 = FLASH_FWKEY; // Clear WRT bit

    FCTL3 = FLASH_FWKEY | LOCK;  // Set LOCK bit

}



void FlashCharGet(unsigned char *pucData, unsigned short usAddress){

    unsigned char* address = (unsigned char *)0x1000;  // Flash segment D ptr (This time is Initialize Flash segment D ptr)


    *pucData = *(address + usAddress);  // Ram to flash memory

}


void FlashRead(unsigned char *pucData, unsigned short usAddress, unsigned short usCount){

    unsigned char* address = (unsigned char *)0x1000;  // Flash segment D


    for( int i = 0; i < usCount ; i++ ){

        *(pucData + i) = *(address + usAddress + i);  // Ram to flash memory

    }

}



void FlashStringPut(unsigned char *pucData, unsigned short usAddress, unsigned short usCount){

    // Flash segment D ptr, Flash pointer, Initialize Flash pointer

    unsigned char* address = (unsigned char *)0x1000;      

    

    while( FlashBusy() );  // Busy check

    FCTL1 = FLASH_FWKEY | WRT;  // Set WRT bit for write operation    

        

    for( int i = 0; i < usCount ; i++ )

    {

        *(address + usAddress + i) = *(pucData+i);  // Data save

        while( FlashWait() );  // Wait check

    }    

    while( FlashBusy() );  // Busy check

}


void FlashCharWrite(unsigned char ucData, unsigned short usAddress){

    if( FLASH_WRITE_ENABLE )

    {

        IntGlobal(false);

    

        FlashRead( flash, 0, FLASH_SIZE );

        

        flash[usAddress] = ucData;

        

        FlashPutEnable();

        FlashStringPut( flash, 0, FLASH_SIZE);

        FlashPutDisable();

    

        IntGlobal(true);

    }

}


void FlashWrite(unsigned char *pucData, unsigned short usAddress, unsigned short usCount){

    if( FLASH_WRITE_ENABLE ){

        IntGlobal(false);

        

        FlashRead( flash, 0, FLASH_SIZE );

        

        for( int i = 0; i < usCount ; i++ ){

            flash[usAddress + i ] = *(pucData+i);          // Data save

        }

        

        FlashPutEnable();

        FlashStringPut( flash, 0, FLASH_SIZE);

        FlashPutDisable();

        

        IntGlobal(true);

    }

}





Posted by klisty
,

IAR Embedded Workbench IDE를 처음 사용자를 위한 사용법을 구글 프리젠테이션으로 정리하였습니다. 아래 프리젠테이션 만 따라 하신다면 MSP를 처음 사용하는 분이더라도 MSP430 MCU에 예제 정도는 다운로드 하실 수 있으 실 것입니다.


또한 사진이 안 보이거나 그럴수 있어서 다음의 주소로 캡쳐화면의 원본과 프린젠테이션을 올려 놓았으니 참고 하시면 될 것 같습니다.

https://docs.google.com/folder/d/0B6FeAfTHOXQYaExrYS1kUS1YZjg/edit




Posted by klisty
,