Search

2013年9月29日 星期日

ATmega328P-AU With UNO Bootloader

    最近想到拿ATmega328P-AU寫入Arduino UNO Bootloader來快速做個樣品給人看,結果今天Layout好了零件焊上完全無法用Arduino ISP的方式寫入Bootloader,一直朝更改Boards.txt與avrdude.conf的方向去走,結果弄了幾個小時想到把當作ISP的Digital 10直接接到ATmega328P-AU的Reset,不是走原本預留給Upload程式用的Auto Reset線路上有個104P電容,就可以寫入Bootloader了,不知道為什麼Digital 10多走一個104P電容就沒辦法,總之ATmega328P-AU寫入Arduino UNO Bootloader跟ATmega328P-PU一樣,接下來可以改作STM32F1的cost down版本。



=============2014/01/06===============


    如果發現Upload程式失敗可能是Upload的過程中被原先的程式佔用(?),可以Reset或者改接3.3v供電再試幾次就可以了。




=============2016/07/19===============
若在燒錄bootloader時發生錯誤可以在ArduinoISP board上的RESET與GND並聯一個10uF的電容。

2013年9月26日 星期四

三個月的近況...

  話說Blog荒廢三個月以上幾乎快忘記這邊的存在了,現在除了忙案子和開發公司的產品之外還有研究所要準備,以及大大小小的比賽和畢業專題...還是記錄一下這三個月在幹嘛好了

  大約在去年十二月左右強者我班上同學就想拉我去他開的公司(Doit 杜瓦行銷有限公司),不過一開始我因為案子很多還有我對當時想產品實在沒有興趣,所以我只有說等到有我有興趣的東西再去幫忙,五月左右聽到一個不錯的想法後就答應七月中處理完日檢還有帶女友回高雄老家玩後,就去桃園中壢公司住到開學全力開發產品雛形跟腦力激盪新產品,這兩個月都在弄指紋機、RFID和各種影像處理程式和奇怪的程式與公司內的Hackday XD。


  這兩個月其實很好玩,我覺得中壢生活比想像中的好,在我心中大約高雄 > 中壢 > 台中這樣吧,基本上能吃的都吃過了該去看的也都有,而且不知道為什麼總覺得中壢生態很好半夜都能聽到公司外的蟲叫,總之現在我們只是四人的新創公司,正在全力研發我們的新產品,因為人少的原因常常得一人Cover很多技術或公司內部等等的東西。


  開學到現在也要兩週了,都在忙比賽的文件和研究所甄試資料,這學期光比賽就被叫去參加四個以上,還有研究所推甄文件也要在十月五號前生出來才保險,畢業專題就等老師要看什麼就給什麼就好XD總之這學期真的很忙,還有女友、案子等等的事情...,雙手抓住太多東西真的怕什麼都會弄不好...XDZ

Arduino - RFID NXP MFRC522

  MFRC522是飛利浦的13.56Mhz的RFID Solution,悠遊卡或者高雄一卡通用的,本來想說要自己Layout洗板,不過因為沒熱風槍不知道怎麼黏MFRC522,總之只要按照Document由SPI傳操作暫存器跟指令就可以用了,Mifare One卡的Block 0前面4byte就是UID,第5byte是校驗和由UID的4byte依序XOR沒錯誤就會得到和第5byte相同的值,另外就是一開始很那悶為什麼得到的UID和iBon不同,原來要轉換成8H10D的格式,將Block 0前面4byte十六進位值反向然後直接視為一個4byte的十進位值就是8H10D了,例如得到:0x12 0x34 0x56 0x78 -> 8H10D:0x78563412 = 2018915346,如果不滿十位數就在開頭補零,最後在網路上看到很多Library不過都很亂所以我重寫整理一下和加入一個8H10D格式的example。


                 Arduino                     MFRC522
            Digital 10            ---->     SDA
            Digital 11(MOSI)  ----> MOSI(DI)
            Digital 12(MISO)  ----> MISO(DO)
            Digital 13(SCK) ----> SCLK(CK)
            Digital 5              ---->      RST
                VCC 3.3V  ---->      VCC
                    GND    ---->      GND

MFRC522.h

#ifndef __MFRC522__
#define __MFRC522__


#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

#include <SPI.h>

//data array maxium length
const unsigned int MAX_LEN = 16;

//MFRC522 command bits
const unsigned char PCD_IDLE = 0x00; //NO action; cancel current commands
const unsigned char PCD_AUTHENT = 0x0E; //verify password key
const unsigned char PCD_RECEIVE = 0x08; //receive data
const unsigned char PCD_TRANSMIT = 0x04; //send data
const unsigned char PCD_TRANSCEIVE = 0x0C; //send and receive data
const unsigned char PCD_RESETPHASE = 0x0F; //reset
const unsigned char PCD_CALCCRC = 0x03; //CRC check and caculation

//Mifare_One card command bits
const unsigned char PICC_REQIDL = 0x26; //Search the cards that not into sleep mode in the antenna area
const unsigned char PICC_REQALL = 0x52; //Search all the cards in the antenna area
const unsigned char PICC_ANTICOLL = 0x93; //prevent conflict
const unsigned char PICC_SElECTTAG = 0x93; //select card
const unsigned char PICC_AUTHENT1A = 0x60; //verify A password key
const unsigned char PICC_AUTHENT1B = 0x61; //verify B password key
const unsigned char PICC_READ = 0x30; //read
const unsigned char PICC_WRITE = 0xA0; //write
const unsigned char PICC_DECREMENT = 0xC0; //deduct value
const unsigned char PICC_INCREMENT = 0xC1; //charge up value
const unsigned char PICC_RESTORE = 0xC2; //Restore data into buffer
const unsigned char PICC_TRANSFER = 0xB0; //Save data into buffer
const unsigned char PICC_HALT = 0x50; //sleep mode


//THe mistake code that return when communicate with MFRC522
const unsigned char MI_OK = 0;
const unsigned char MI_NOTAGERR = 1;
const unsigned char MI_ERR = 2;


//------------------MFRC522 register ---------------
//Page 0:Command and Status
const unsigned char Reserved00 = 0x00;
const unsigned char CommandReg = 0x01;
const unsigned char CommIEnReg = 0x02;
const unsigned char DivlEnReg = 0x03;
const unsigned char CommIrqReg = 0x04;
const unsigned char DivIrqReg = 0x05;
const unsigned char ErrorReg = 0x06;
const unsigned char Status1Reg = 0x07;
const unsigned char Status2Reg = 0x08;
const unsigned char FIFODataReg = 0x09;
const unsigned char FIFOLevelReg = 0x0A;
const unsigned char WaterLevelReg = 0x0B;
const unsigned char ControlReg = 0x0C;
const unsigned char BitFramingReg = 0x0D;
const unsigned char CollReg = 0x0E;
const unsigned char Reserved01 = 0x0F;
//Page 1:Command
const unsigned char Reserved10 = 0x10;
const unsigned char ModeReg = 0x11;
const unsigned char TxModeReg = 0x12;
const unsigned char RxModeReg = 0x13;
const unsigned char TxControlReg = 0x14;
const unsigned char TxAutoReg = 0x15;
const unsigned char TxSelReg = 0x16;
const unsigned char RxSelReg = 0x17;
const unsigned char RxThresholdReg = 0x18;
const unsigned char DemodReg = 0x19;
const unsigned char Reserved11 = 0x1A;
const unsigned char Reserved12 = 0x1B;
const unsigned char MifareReg = 0x1C;
const unsigned char Reserved13 = 0x1D;
const unsigned char Reserved14 = 0x1E;
const unsigned char SerialSpeedReg = 0x1F;
//Page 2:CFG
const unsigned char Reserved20 = 0x20;
const unsigned char CRCResultRegM = 0x21;
const unsigned char CRCResultRegL = 0x22;
const unsigned char Reserved21 = 0x23;
const unsigned char ModWidthReg = 0x24;
const unsigned char Reserved22 = 0x25;
const unsigned char RFCfgReg = 0x26;
const unsigned char GsNReg = 0x27;
const unsigned char CWGsPReg = 0x28;
const unsigned char ModGsPReg = 0x29;
const unsigned char TModeReg = 0x2A;
const unsigned char TPrescalerReg = 0x2B;
const unsigned char TReloadRegH = 0x2C;
const unsigned char TReloadRegL = 0x2D;
const unsigned char TCounterValueRegH = 0x2E;
const unsigned char TCounterValueRegL = 0x2F;
//Page 3:TestRegister
const unsigned char Reserved30 = 0x30;
const unsigned char TestSel1Reg = 0x31;
const unsigned char TestSel2Reg = 0x32;
const unsigned char TestPinEnReg = 0x33;
const unsigned char TestPinValueReg = 0x34;
const unsigned char TestBusReg = 0x35;
const unsigned char AutoTestReg = 0x36;
const unsigned char VersionReg = 0x37;
const unsigned char AnalogTestReg = 0x38;
const unsigned char TestDAC1Reg = 0x39;
const unsigned char TestDAC2Reg = 0x3A;
const unsigned char TestADCReg = 0x3B;
const unsigned char Reserved31 = 0x3C;
const unsigned char Reserved32 = 0x3D;
const unsigned char Reserved33 = 0x3E;
const unsigned char Reserved34 = 0x3F;
//-----------------------------------------------

class MFRC522
{
public:
MFRC522();

void Write(const unsigned char,const unsigned char);
unsigned char Read(const unsigned char);
void SetBitMask(const unsigned char,const unsigned char);
void ClearBitMask(const unsigned char,const unsigned char);
void AntennaOn();
void AntennaOff();
void Reset();
void Init();

unsigned char MFRC522ToCard(const unsigned char,
const unsigned char*,
const unsigned char,
unsigned char*,
unsigned int*);
unsigned char WriteBlock(unsigned char,unsigned char*);
unsigned char Request(unsigned char,unsigned char*);
unsigned char Anticoll(unsigned char*);
void CalulateCRC(unsigned char*,unsigned char,unsigned char*);
unsigned char SelectTag(unsigned char*);
void Halt();
private:
const static int chip_select_pin = 10;
const static int NRSTPD = 5;
};

#endif

MFRC522.cpp

#include <MFRC522.h>

#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

MFRC522::MFRC522()
{
pinMode(chip_select_pin,OUTPUT);
digitalWrite(chip_select_pin,LOW);

    pinMode(NRSTPD,OUTPUT);
digitalWrite(NRSTPD,HIGH);
}

void MFRC522::Write(const unsigned char address,const unsigned char value)
{
digitalWrite(chip_select_pin,LOW);
SPI.transfer((address << 1) & 0x7E);
    SPI.transfer(value);
digitalWrite(chip_select_pin,HIGH);
}

unsigned char MFRC522::Read(const unsigned char address)
{
unsigned char value;

digitalWrite(chip_select_pin,LOW);
    SPI.transfer(((address << 1) & 0x7E) | 0x80);
    value = SPI.transfer(0x00);
digitalWrite(chip_select_pin,HIGH);

return value;
}

void MFRC522::SetBitMask(const unsigned char reg,const unsigned char mask)
{
    unsigned char temp;
    temp = Read(reg);
    Write(reg,temp | mask);
}

void MFRC522::ClearBitMask(const unsigned char reg,const unsigned char mask)
{
    unsigned char temp;
    temp = Read(reg);
    Write(reg,temp & (~mask)); // clear bit mask
}

void MFRC522::AntennaOn()
{
    unsigned char temp;

    temp = Read(TxControlReg);
    if(!(temp & 0x03)){
SetBitMask(TxControlReg,0x03);
}
}

void MFRC522::AntennaOff()
{
ClearBitMask(TxControlReg,0x03);
}

void MFRC522::Reset()
{
Write(CommandReg,PCD_RESETPHASE);
}

void MFRC522::Init()
{
Reset();

    Write(TModeReg,0x8D);
    Write(TPrescalerReg,0x3E);
    Write(TReloadRegL,30);
    Write(TReloadRegH,0);
   
    Write(TxAutoReg,0x40);
    Write(ModeReg,0x3D);

AntennaOn();
}

unsigned char MFRC522::MFRC522ToCard(const unsigned char command,const unsigned char *send_data,const unsigned char send_len,unsigned char *back_data,unsigned int *back_len)
{
    unsigned char status = MI_ERR;
    unsigned char irqEn = 0x00;
    unsigned char waitIRq = 0x00;
    unsigned char lastBits;
    unsigned char n;
    unsigned int i;

    switch(command)
    {
        case PCD_AUTHENT: //verify card password
        {
            irqEn = 0x12;
            waitIRq = 0x10;
            break;
        }
        case PCD_TRANSCEIVE: //send data in the FIFO
        {
            irqEn = 0x77;
            waitIRq = 0x30;
            break;
        }
        default:
            break;
    }
 
    Write(CommIEnReg,irqEn | 0x80); //Allow interruption
    ClearBitMask(CommIrqReg,0x80); //Clear all the interrupt bits
    SetBitMask(FIFOLevelReg,0x80); //FlushBuffer=1, FIFO initilizate
   
    Write(CommandReg,PCD_IDLE); //NO action;cancel current command ???

    //write data into FIFO
    for (i = 0; i < send_len;++i){
        Write(FIFODataReg,send_data[i]);
    }

    //procceed it
    Write(CommandReg,command);
    if (command == PCD_TRANSCEIVE){
SetBitMask(BitFramingReg,0x80); //StartSend=1,transmission of data starts
    }
   
    //waite receive data is finished
    i = 2000; //i should adjust according the clock, the maxium the waiting time should be 25 ms???
    do {
        //CommIrqReg[7..0]
        //Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
        n = Read(CommIrqReg);
        --i;
    }

    while ((i != 0) && !(n & 0x01) && !(n & waitIRq));

    ClearBitMask(BitFramingReg,0x80); //StartSend=0
   
    if (i != 0){
if(!(Read(ErrorReg) & 0x1B)){ //BufferOvfl Collerr CRCErr ProtecolErr
            status = MI_OK;
            if(n & irqEn & 0x01){
                status = MI_NOTAGERR; //??
            }
           
            if(command == PCD_TRANSCEIVE){
                n = Read(FIFOLevelReg);
                lastBits = Read(ControlReg) & 0x07;
                if (lastBits){
                    *back_len = (n - 1) * 8 + lastBits;
                }
                else{
                    *back_len = n*8;
                }
               
                if(n == 0){
                    n = 1;
                }
                if (n > MAX_LEN){
                    n = MAX_LEN;
                }
               
                //read the data from FIFO
                for (i=0; i < n;++i){
                    back_data[i] = Read(FIFODataReg);
                }
            }
        }
        else{
            status = MI_ERR;
        }
       
    }
   
    //SetBitMask(ControlReg,0x80); //timer stops
    //Write(CommandReg, PCD_IDLE);

    return status;
}

unsigned char MFRC522::WriteBlock(unsigned char block_address,unsigned char  *write_data)
{
    unsigned char status;
    unsigned int recvBits;
    unsigned char i;
    unsigned char buff[18];
   
    buff[0] = PICC_WRITE;
    buff[1] = block_address;
    CalulateCRC(buff,2,&buff[2]);
    status = MFRC522ToCard(PCD_TRANSCEIVE,buff,4,buff,&recvBits);

    if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)){
        status = MI_ERR;
    }
       
    if (status == MI_OK){
for (i=0;i < 16;++i){ //Write 16 bytes data into FIFO
            buff[i] = *(write_data+i);
        }
        CalulateCRC(buff,16,&buff[16]);
        status = MFRC522ToCard(PCD_TRANSCEIVE,buff,18,buff,&recvBits);
       
        if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)){
            status = MI_ERR;
        }
    }
   
    return status;
}

unsigned char MFRC522::Request(unsigned char mode,unsigned char *tag_type)
{
    unsigned char status;
    unsigned int backBits; //the data bits that received

    Write(BitFramingReg,0x07); //TxLastBists = BitFramingReg[2..0] ???
   
    tag_type[0] = mode;
    status = MFRC522ToCard(PCD_TRANSCEIVE,tag_type,1,tag_type,&backBits);

    if ((status != MI_OK) || (backBits != 0x10)){
        status = MI_ERR;
    }
 
    return status;
}

unsigned char MFRC522::Anticoll(unsigned char *uid)
{
    unsigned char status;
    unsigned char i;
    unsigned char serNumCheck=0;
    unsigned int unLen;
   
    //ClearBitMask(Status2Reg, 0x08); //strSensclear
    //ClearBitMask(CollReg,0x80); //ValuesAfterColl
    Write(BitFramingReg,0x00); //TxLastBists = BitFramingReg[2..0]

    uid[0] = PICC_ANTICOLL;
    uid[1] = 0x20;
    status = MFRC522ToCard(PCD_TRANSCEIVE,uid,2,uid,&unLen);

    if (status == MI_OK){
        //Verify card UID
        for (i=0;i < 4;++i){
            serNumCheck ^= uid[i];
        }
        if (serNumCheck != uid[i]){
            status = MI_ERR;
        }
    }

    //SetBitMask(CollReg, 0x80); //ValuesAfterColl=1

    return status;
}

void MFRC522::CalulateCRC(unsigned char *input,unsigned char len,unsigned char *output)
{
    unsigned char i,n;

    ClearBitMask(DivIrqReg,0x04); //CRCIrq = 0
    SetBitMask(FIFOLevelReg,0x80); //Clear FIFO pointer
    //Write(CommandReg, PCD_IDLE);

    //Write data into FIFO
    for (i=0;i < len;i++){
        Write(FIFODataReg,*(input + i));
    }
    Write(CommandReg,PCD_CALCCRC);

    //waite CRC caculation to finish
    i = 0xFF;
    do {
        n = Read(DivIrqReg);
        --i;
    }
    while ((i != 0) && !(n & 0x04)); //CRCIrq = 1

    //read CRC caculation result
    output[0] = Read(CRCResultRegL);
    output[1] = Read(CRCResultRegM);
}

unsigned char MFRC522::SelectTag(unsigned char *uid)
{
unsigned char i;
unsigned char status;
unsigned char size;
unsigned int recvBits;
unsigned char buffer[9];

//ClearBitMask(Status2Reg, 0x08);                        //MFCrypto1On=0

buffer[0] = PICC_SElECTTAG;
buffer[1] = 0x70;

for (i=0; i<5; i++){
    buffer[i + 2] = *(uid + i);
}

  CalulateCRC(buffer,7,&buffer[7]);

  status = MFRC522ToCard(PCD_TRANSCEIVE,buffer,9,buffer,&recvBits);
  if ((status == MI_OK) && (recvBits == 0x18)){
    size = buffer[0];
  }
  else{
    size = 0;
  }

  return size;
}

void MFRC522::Halt()
{
    unsigned char status;
    unsigned int unLen;
    unsigned char buff[4];

    buff[0] = PICC_HALT;
    buff[1] = 0;
    CalulateCRC(buff,2,&buff[2]);

    status = MFRC522ToCard(PCD_TRANSCEIVE,buff,4,buff,&unLen);
}


8H10D.ino

#include <MFRC522.h>
#include <SPI.h>

/* 16^0 ~ 16^7 */
unsigned long table[8] = {1,16,256,4096,65536,1048576,16777216,268435456};

MFRC522 mfrc522;

unsigned char uid[5];

void setup()
{
  Serial.begin(9600);
  SPI.begin();
  mfrc522.Init();
}

void loop()
{
  unsigned char status;
  unsigned char str[MAX_LEN];

  status = mfrc522.Request(PICC_REQIDL,str);
  if (status != MI_OK){
    return;
  }

  status = mfrc522.Anticoll(str);
  if (status == MI_OK){
    memcpy(uid,str,5);
    mfrc522.SelectTag(uid); //防止同張卡片持續感應與讀取
 
    Serial.print("Original UID : ");
    unsigned long sum = 0; //將UID每位byte加總(4byte uid & 1byte check)
    for(int i = 3;i >= 0;--i){
      unsigned long temp_h = (uid[i] >> 4) & 0x0000000F;
      Serial.print(temp_h,HEX);
      sum += (temp_h * table[(i*2)+1]); //加上UID每byte的高4bit
      unsigned long temp_l = (uid[i] & 0x0000000F);
      Serial.print(temp_l,HEX);
      sum += (temp_l * table[i*2]); //加上UID每byte的低4bit
    }
    Serial.println("");
 
    Serial.print("8H10D UID : ");
    String _8H10D = String(sum);
    if(_8H10D.length() < 10){
      for(int i = 0;i < (10 - _8H10D.length());++i){
        Serial.print("0"); //8H10D格式未滿十碼開頭補零
      }
    }
    for(int i = 0;i < _8H10D.length();++i){
      Serial.print(_8H10D.charAt(i));
    }
  }
  Serial.println("");

  mfrc522.Halt();
  delay(100);
}

參考

MFRC522 Datasheet