📄 f_12_20_i2c_dac.c
字号:
// For MCC18, this file uses the -Oi flag, which
// turns on integer promotions so that (ADRESH << 8) works.
#include "config.h"#include "delay.h"#include "serial.c"#include "serio.c"#include "i2cmsu.c"#include "jwb.h"/* * program to generate sine wave output on RB7..RB0 using * R-2R resistor ladder and other waveforms on MAX518 */// FUNCTION PROTOTYPESint ReadAdcChannel(unsigned char c);void WriteMAX518(unsigned char c0, unsigned char c1);// GLOBAL VARIABLES AND STATIC DATAvolatile unsigned char itmr, iamp, doAdc;unsigned char idx, cnt;#if defined(__18CXX)rom#endif const unsigned char sinetbl[] = {127,133,139,146,152,158,164,170, \ 176,181,187,192,198,203,208,212,217,221,225,229,233,236,239, \ 242,244,247,249,250,252,253,253,254,254,254,253,253,252,250, \ 249,247,244,242,239,236,233,229,225,221,217,212,208,203,198, \ 192,187,181,176,170,164,158,152,146,139,133,127,121,115,108, \ 102,96,90,84,78,73,67,62,56,51,46,42,37,33,29,25,21,18,15,12, \ 10,7,5,4,2,1,1,0,0,0,1,1,2,4,5,7,10,12,15,18,21,25,29,33,37, \ 42,46,51,56,62,67,73,78,84,90,96,102,108,115,121 };#if defined(HI_TECH_C)void interrupt pic_isr(void)#endif#if defined(__18CXX)#pragma interrupt pic_isrvoid pic_isr(void)#endif{ unsigned char temp0, temp1; if (TMR2IF) { TMR2IF = 0; // clear IRQ flag // TOGGLE(RC2); temp0 = sinetbl[idx]; // get sine fcn value temp0 >>= iamp; // reduce amplitude based on AN1 input PORTB = temp0; // write new R-2R DAC value temp0 = 0; if (idx & 0x40) temp0=(0xFF>>iamp); else temp0=0; temp1 = idx<<1; temp1>>=iamp; WriteMAX518(temp0,temp1); idx++; idx+=itmr; idx&=0x7F; // increment ptrs for next if (++cnt == 0) doAdc=1; // signal main() to read ADC } // end if} // end pic_isr// use ADC to convert channel denoted by c and returns result in int// NOTE: Assumes ADC is already on and proper ADC clk is selectedint ReadAdcChannel(unsigned char c) { unsigned char temp; temp = ADCON0 & 0xC1; // get current ADCON0 (clearing CHS2:CHS0) ADCON0 = temp | ((c & 0x7)<<3); // select the desired ADC channel DelayUs(20); // wait 20us for ADC to get ready GODONE = 1; // start ADC conversion, while(GODONE); // then wait for ADC to finish if ( ADFM ) return ((ADRESH << 8) | ADRESL ); else return ((ADRESH << 2) | (ADRESL>>6) );} // end ReadAdcChannel// write c0 to MAX518 DAC0 and c1 to DAC1void WriteMAX518(unsigned char c0, unsigned char c1) { i2c_start(); i2c_put(0x58); // start I2C xfer by sending MAX518 addr i2c_put(0x00); i2c_put(c0); // MAX518 cmd to write D0, then D0 data i2c_put(0x01); i2c_put(c1); // MAX518 cmd to write D1, then D1 data i2c_stop(); // finish I2C xfer} // end WriteMAX518void main(void){ int temp; SET_AS_OUTPUT(TRISA, BIT1 | BIT2 | BIT3 | BIT5 | BIT6 | BIT7 ); SET_AS_INPUT(TRISA, BIT0 | BIT1 | BIT3); PORTB = 0x00; SET_AS_OUTPUT(TRISB, BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 ); SET_AS_OUTPUT(TRISC, BIT2); // configure number of ADC channels and references (AN0+AN1+AN3+ no Vrefs) PCFG3=0; PCFG2=1; PCFG1=0; PCFG0=0; // set ADC conversion clock to internal ADC clock ADCS2=1; ADCS1=1; ADCS0=1; // select ADC channel 0 CHS2=0; CHS1=0; CHS0=0; // set ADC results to be left justified (ADRESH has MSB) ADFM=0; // turn on ADC ADON=1; // wait before we kick off a conversion DelayUs(100); idx=0; cnt=0; itmr=0; iamp=0; doAdc=0; // init ISR variables //i2c_init(7); // init I2C bus to 1 Mbps !!!!! WON'T WORK !!!!!! //i2c_init(9); // init I2C bus to approx 700 Kbps !!! SEEMS TO WORK OK !!! i2c_init(14); // init I2C bus to 500 Kbps !!! SHOULD WORK FOR MOST !!! //i2c_init(18); // init I2C bus to 400 Kbps //i2c_init(72); // init I2C bus to 100 Kbps // configure TMR2 and turn it on PR2 = 246; // setup IRQs every ??? cycles (6000Hz) T2CON = (((5-1)<<3)|0x04); // 1:5 post, 1:1 pre, turn on TMR2 TMR2IF = 0; // clear flag before enabling IRQ IPEN = 0; TMR2IE = 1; PEIE = 1; GIE = 1; // enable TMR2 interrupts while(1) { doAdc=0; while (doAdc==0); temp = ReadAdcChannel(0); itmr = temp>>5; // make itmr 0-127 doAdc=0; while (doAdc==0); temp = ReadAdcChannel(1); iamp = temp>>8; // make iamp 0-3 } // end while} // end main()//for MCC18, place the interrupt vector goto#if defined(__18CXX)#if defined(HIGH_INTERRUPT)#pragma code HighVector=HIGH_INTERRUPT#else#pragma code HighVector=0x0008 #endifvoid HighVector (void){ _asm goto pic_isr _endasm}#pragma code#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -