📄 f_12_16_r2r_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 "jwb.h"/* * program to generate square wave output on RB7..RB0 using * R-2R resistor ladder and TMR2 interrupts */// FUNCTION PROTOTYPESint ReadAdcChannel(unsigned char c);// GLOBAL VARIABLES AND STATIC DATAvolatile unsigned char itmr, iamp;unsigned char idx;#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 temp; if (TMR2IF) { temp = sinetbl[idx]; // get sine fcn value temp >>= iamp; // reduce amplitude based on AN1 input PORTB = temp; // write new DAC value TMR2IF = 0; // clear IRQ flag PR2 = 250-itmr; // change TMR2 period based on AN0 input idx++; // increment ptr for next update idx &= 0x7F; // ensure ptr is in range } // 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 ReadAdcChannelvoid 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 ); // 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; itmr = 0; iamp = 0; // init ISR variables // configure TMR2 and turn it on PR2 = 250; // setup IRQs every 250 cycles T2CON = 0x04; // 1:1 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) { temp = ReadAdcChannel(0); itmr = temp>>3; // make itmr 0-127 DelayMs(50); // wait a long time temp = ReadAdcChannel(1); iamp = temp>>8; // make iamp 0-3 DelayMs(50); // wait a long time } // 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 + -