# MCP3421_電壓偵測IC [MCB3421 datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/22003e.pdf) ###### tags:`datasheet` `mcp3421` `PIC16F18854` <style> .red {color:red;} </style> ## IC封裝與腳位  ## 寫入控制暫存器  ### <span class ="red">$\bar {RAY}$</span>:準備位 用**讀取**命令讀取RDY位:\ 1 =輸出寄存器尚未更新。\ 0 =輸出寄存器已更新為最新的轉換結果。\ \ 用**寫**命令寫RDY位:\ 連續轉換模式:無影響\ \ 單次轉換模式:\ 1 =啟動新轉換。\ 0 =無效果。 ### <span class ="red">$\bar O/C$</span>:轉換模式位 1 =連續轉換模式(默認)。 該設備連續執行數據轉換。\ 0 =單次轉換模式。器件執行單次轉換並進入低功耗待機模式,直到收到另一個寫或讀命令為止。 ### <span class ="red">${S1-S0(3:2)}$</span>:採樣率選擇位 00 = 240 SPS (12 bits) (預設)\ 01 = 60 SPS (14 bits)\ 10 = 15 SPS (16 bits\ 11 = 3.75 SPS (18 bits) ### <span class ="red">${G1-G0(1:0)}$</span>:PGA增益選擇位 00 = x1(預設) 01 = x2 10 = x4 11 = x8 ## 使用方式 ::: info ### 接線方式  $量測的電壓={OutPut\ Code}_{(10)}\times下下表對應的LSB\times{{R_1+R_2}\over R_2}\times {1\over 所設定的PGA}$ ::: ::: warning ### OutPut Code  可以用這個驗證output code正確與否\ \ 其中的2.048v就代表${V_{in}}^++-{V_{in}}^-$不可以超過2.048v,不然再成Maximum Code與PGA的值會超過Maximum Code能表示的範圍,所以如果要量測比2.048V大就要將電壓經過分壓後再讀取進來,如前面的接線方式圖 ### 每階可以辨識的電壓  可以想像成將2.048v 區分成很多等份,而每一等份的實際電壓為LSB 例如: 用12bits的可以1mV的精度分辨 ### 公式可以用到的對照表  MSB(最高位)是用來表是量測電壓的正負,0為正、1為負 \ 例如: 用12bits的最高值是 ${(0111\ 1111\ 1111)}_{(2)}\ = \ 2047_{(10)}$ ### 如何閱讀輸出的二進制  為了1個byte1個byte對應著SCL的顯示,所以如果是無法用1byte(8bits)整除的轉換選項就會在最高位元側顯示這筆data的MSB,也就是標示正負號的位元 \ 例如: 12bits模式的$D11-D0=(1111\ 00000\ 0000)_{(2)}$,其MSB為'1',所以會顯示成$(1111\ 1111\ 00000\ 0000)_{(2)}$ 要捨棄掉最前面重複的MSB才是用來計算的Output Code ### 計算量測電壓實際值  例如: $12bits\ 模式\\Outtput\ Code={(1010\ 1010\ 1010)}_{(2)}=(-682)_{(10)}對應的LSB為1mV\\R_1=R_2=1kΩ\\PGA=1$ \ 則: 量測電壓為$=-682 \times 1m \times {{1k+1k}\over 1k} \times {1\over1}=-1.364V$ ::: ::: success ### 要來寫程式了喔 #### WRITE  $START \to 7位地址+寫位(0) \to 寫入控制暫存器8位 \to STOP$ **地址位為1101000** #### READ  $START \to 7位地址+讀位(1) \to 讀到的資料 \to 寫入控制暫存器8位 \to STOP$ 如果要停止讀出資料就傳送STOP或是NACK 在"寫入控制暫存器8位"之後如果還繼續有SCL產生(例如還沒STOP)就會一直重複著"寫入控制暫存器8位" 本篇所有的"$\to$"都是ACK ### 程式說明 ::: spoiler ### 大家都要有的初始化 ```c= void init(void){ PMD_Initialize(); PIN_MANAGER_Initialize(); OSCILLATOR_Initialize(); } void OSCILLATOR_Initialize(void){ // NOSC HFINTOSC; NDIV 1; OSCCON1 = 0x60; // CSWHOLD may proceed; SOSCPWR Low power; OSCCON3 = 0x00; // MFOEN disabled; LFOEN disabled; ADOEN disabled; SOSCEN disabled; EXTOEN disabled; HFOEN disabled; OSCEN = 0x00; // HFFRQ 4_MHz; OSCFRQ = 0x02; // HFTUN 0; OSCTUNE = 0x00; } void PMD_Initialize(void){ // CLKRMD CLKR enabled; SYSCMD SYSCLK enabled; SCANMD SCANNER enabled; FVRMD FVR enabled; IOCMD IOC enabled; CRCMD CRC enabled; NVMMD NVM enabled; PMD0 = 0x00; // TMR0MD TMR0 enabled; TMR1MD TMR1 enabled; TMR4MD TMR4 enabled; TMR5MD TMR5 enabled; TMR2MD TMR2 enabled; TMR3MD TMR3 enabled; NCOMD DDS(NCO) enabled; TMR6MD TMR6 enabled; PMD1 = 0x00; // ZCDMD ZCD enabled; DACMD DAC enabled; CMP1MD CMP1 enabled; ADCMD ADC enabled; CMP2MD CMP2 enabled; PMD2 = 0x00; // CCP2MD CCP2 enabled; CCP1MD CCP1 enabled; CCP4MD CCP4 enabled; CCP3MD CCP3 enabled; CCP5MD CCP5 enabled; PWM6MD PWM6 enabled; PWM7MD PWM7 enabled; PMD3 = 0x00; // CWG3MD CWG3 enabled; CWG2MD CWG2 enabled; CWG1MD CWG1 enabled; MSSP1MD MSSP1 enabled; UART1MD EUSART enabled; MSSP2MD MSSP2 enabled; PMD4 = 0x00; // DSMMD DSM enabled; CLC3MD CLC3 enabled; CLC4MD CLC4 enabled; SMT1MD SMT1 enabled; SMT2MD SMT2 enabled; CLC1MD CLC1 enabled; CLC2MD CLC2 enabled; PMD5 = 0x00; } void PIN_MANAGER_Initialize(void){ /** LATx registers */ LATA = 0x00; LATB = 0x00; LATC = 0x00; /** TRISx registers */ TRISA = 0x00; TRISB = 0xFF; TRISC = 0xFF; /** ANSELx registers */ ANSELC = 0xE7;//RC3 RC4設為數位 ANSELB = 0xFF; ANSELA = 0x00;//PORTA 設為數位 /** WPUx registers */ WPUE = 0x00; WPUB = 0x00; WPUA = 0x00; WPUC = 0x00; /** ODx registers */ ODCONA = 0x00; ODCONB = 0x00; ODCONC = 0x00; /** SLRCONx registers */ SLRCONA = 0xFF; SLRCONB = 0xFF; SLRCONC = 0xFF; /** INLVLx registers */ INLVLA = 0x00; INLVLB = 0xFF; INLVLC = 0xFF; INLVLE = 0x08; //智能SDA和SCL兩隻腳 SSP1CLKPPS = 0x13; //RC3->MSSP1:SCL1; RC3PPS = 0x14; //RC3->MSSP1:SCL1; RC4PPS = 0x15; //RC4->MSSP1:SDA1; SSP1DATPPS = 0x14; //RC4->MSSP1:SDA1; } ``` #### master暫存器設定 ```c= void master_init(void){ INTCONbits.GIE = 0;//中斷不智能 INTCONbits.PEIE = 0;//中斷不智能 PIR3bits.SSP1IF = 1;//等待傳輸 PIR3bits.BCL1IF = 1;//未檢測到衝突 PIE3bits.SSP1IE = 0;//不允許中斷 PIE3bits.BCL1IE = 0;//衝突不允許中斷 SSP1CON1=0x28; //智能SDA和SCL兩隻腳與設定為I2C master模式 SSP1CON2=0x00; SSP1CON3=0x00; SSP1STAT=0x00; SSP1BUF =0x00; SSP1STATbits.SMP=1; //1 =在標準速度模式(100 kHz和1 MHz)下禁用slew rate control SSP1STATbits.CKE=1; //1 =智能輸入邏輯,以使閾值符合SMBus規範 SSP1ADD=0x06; //100k Hz=0x06 數字越高頻率越慢 SSP1MSK=0xFF; //理論上這個在master應該是沒有用的,但還是讓她都為1乖一點 RA3=1; //可以用來看這個時候轉換成master了 } ``` #### 等等喔 ```c= void I2C_Master_Wait(){ while ((SSP1STAT & 0x04) || (SSP1CON2 & 0x1F));//確認有發起start後再動作 } ``` #### start ```c= void I2C_Master_Start(){ I2C_Master_Wait(); SSP1CON2bits.SEN = 1; //start } ``` #### restart ```c= void I2C_Master_RepeatedStart(){ I2C_Master_Wait(); SSP1CON2bits.RSEN = 1; //restart } ``` #### stop ```c= void I2C_Master_Stop(){ I2C_Master_Wait(); SSP1CON2bits.PEN = 1; //stop } ``` #### 寫入 ```c= void I2C_Master_Write(uint8_t data){ I2C_Master_Wait(); SSP1BUF = data; //將要傳送的data放進要經由I2C傳出的buffer裡 while(!PIR3bits.SSP1IF); // 等待bus上空閒 PIR3bits.SSP1IF = 0; //傳輸完成之後會為1,要用軟體回歸0,代表做完事了 } ``` #### 讀取 ```c= uint8_t I2C_Master_Read(uint8_t get){//get=0代表所有讀取資料完畢後會回傳nack(通常都是這個) //get=1代表所有讀取資料完畢後會回傳nack uint8_t temp; // 用來儲存讀取的資料的變數 I2C_Master_Wait(); SSP1CON2bits.RCEN = 1; //智能I2C的接收模式 I2C_Master_Wait(); temp = SSP1BUF; //將buffer收到的資料放進用來存取的變數裡 I2C_Master_Wait(); SSP1CON2bits.ACKDT = (get)?0:1;//get=1時,ack_data=NACK(0) //get=0時,ack_data=ACK(1) SSP1CON2bits.ACKEN = 1; //回傳ack_data給發送端 return temp; //引用I2C_Master_Read(uint8_t get)這行函式可得到讀取的資料 } ``` ::: #### main ```c= #define VOLTADE_ADD 0x68 uint8_t slave_feedback1, slave_feedback2; void main(void) { I2C_Master_Start(); I2C_Master_Write((VOLTADE_ADD << 1)|0); //7 bit address + Write(0) I2C_Master_Write(0x90);//也可以不寫,這就是預設狀態 I2C_Master_Stop(); I2C_Master_Start(); I2C_Master_Write((VOLTADE_ADD << 1)|1); //7 bit address + Read(1) slave_feedback1=I2C_Master_Read(1); slave_feedback2=I2C_Master_Read(0);//傳NACK代表是最後一筆資料了 I2C_Master_Stop(); while(1){ ; } } ``` ::: ::: danger ## 注意 **最高位元是用來表示正負號,0為正,1為負** 例如一個12bit的輸出為: 0110 1010 1011,轉成十進制為1707 應該要再加東西 :::
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up