Wednesday, December 11, 2013

DAC 12-bit sweep

I structured up the I2C-code for the PIC and added a proper function for sending data to I2C slave. Ramping the DAC output from 0x000 to 0xFFF, takes about 2.5 seconds, so it's not possible to show a picture of the ramp from my analog scope. I'll still show a picture with the moving dot with the period measured.
Very slow DAC sweep that takes 2.5 seconds
I also tested to toggle the DAC between max and min value to see what the maximum switching time is and if there are any issues with ringing.
Half a DAC switching period.

No visible overshoot or ringing in when DAC is switching.


1:  //Uart RX/TX loop test and I2C transmission test using PIC12F1822  
2:  #include <xc.h>  
3:    
4:  //Configuration bits  
5:  #pragma config WDTE=OFF, PWRTE = OFF, MCLRE=OFF, BOREN=OFF, FCMEN=OFF, CLKOUTEN = OFF, IESO=OFF, FOSC=INTOSC, CPD=OFF, LVP = ON, BORV = 0  
6:    
7:  //This symbol is needed so that __delay_ms() gives a correct delay time  
8:  #define _XTAL_FREQ 4000000  
9:    
10:    
11:  volatile int i2cTransmitCycle; //Counter for I2C transmission cycle steps, which are carried out in the interrupt service routine  
12:  volatile int i2cTransmitInProgress;  
13:  volatile int i2c7bitAddress;   
14:  volatile int i2cData[2]; //Data to be sent  
15:  volatile int i2cDataCounter; //For indication of which byte is to be sent  
16:  volatile int i2cDataNoBytes; //Number of bytes to be sent  
17:    
18:  int i2cTransmit(int, int [], int);  
19:  void i2cTransferDataArray(int [], int);  
20:    
21:  void main() {  
22:    extern int i2cTransmitInProgress;  
23:    extern int i2cData[2];  
24:    
25:    int GPORTA; //Port A ghost variable  
26:    i2cTransmitInProgress = 0;  
27:    PORTA = 0x01; //Set RA0 to light LED  
28:    
29:    //I2C baud rate generator set to Fclock = Fosc/(4(SSP1ADD+1)) = 4MHz/(4(2+1))=333kHz  
30:    SSP1ADD = 0b00000010;  
31:    
32:    //SSP1STAT SSP1 STATUS REGISTER  
33:    //SSP1STAT = 0b0000 0000; //default  
34:    
35:    //SSP1CON1 SSP1 CONTROL REGISTER 1  
36:    //I2C Master mode  
37:    //Serial port pins SDA and SCL enabled  
38:    SSP1CON1 = 0b00101000;  
39:    
40:    //SSP1CON2 SSP1 CONTROL REGISTER 2  
41:    //SSP1CON2 = 0b00000000; //default  
42:    
43:    //SSP1CON3 SSP1 CONTROL REGISTER 3  
44:    //SSP1CON3 = 0b00000000; //default  
45:    
46:    //Set all I/O's to digital  
47:    ANSELA = 0x00;  
48:    
49:    //ALTERNATE PIN FUNCTION CONTROL REGISTER  
50:    //Set UART RX/TX to pins RA5/RA4  
51:    APFCON = 0b10000100;  
52:    
53:    //0 Internal oscillator, 3 <fosc> on, 6-4 4MHz  
54:    OSCCON = 0b01101000;  
55:    
56:    //Interrupt controller  
57:    //6 Peripheral interrupt enabled  
58:    //7 Global interrupt enabled  
59:    INTCON = 0b11000000;  
60:    
61:    //TRISA  
62:    //RA1,2,5 set as input, all other IO's set as output  
63:    TRISA = 0b00100110;  
64:    
65:    //Free running bad rate timer is 7  
66:    SPBRGH = 0x00;  
67:    SPBRGL = 0x07;  
68:    
69:    //TXSTA: TRANSMIT STATUS AND CONTROL REGISTER  
70:    //8-bit transmission, transmit enable, asynchronous mode, high baud rate selected  
71:    //Baud rate is FOSC/[16 (n+1)] = 4MHz/(16 (7+1)) = 31250, approx 31500 symbols/sec  
72:    TXSTA = 0b10100110;  
73:    
74:    //RECEIVE STATUS AND CONTROL REGISTER  
75:    //Serial port enabled, continuous receive enabled  
76:    RCSTA = 0b10010000;  
77:    
78:    //PERIPHERAL INTERRUPT ENABLE REGISTER  
79:    //USART Receive interrupt enabled  
80:    //Synchronous Serial Port (MSSP) Interrupt Enable  
81:    PIE1 = 0b00101000;  
82:    
83:    //Delay 5 seconds before I2C transmission  
84:    __delay_ms(5000);  
85:    
86:    //Small routine for blinking RA0 every five seconds  
87:    //I2C transmission carried out when LED goes off the first time after power on  
88:    //Read latch A into ghost register  
89:    GPORTA = LATA;  
90:    //Toggle bit 0  
91:    GPORTA = GPORTA^(1 << 0);  
92:    //Write back into port register  
93:    PORTA = GPORTA;  
94:    
95:    //Array of data to be sent to I2C bus  
96:    int i2cDataF[2];  
97:    
98:    //12 bit value intended for DAC  
99:    int dacValue = 0;  
100:    
101:    //Loop forever  
102:    while (1) {  
103:      //12 bit DAC value needs to be split into two 8 bit chunks  
104:      //The remainding 4 bits of the first byte is set to zero  
105:      //which is a DAC setting  
106:      i2cDataF[0] = ((dacValue & 0x0F00) >> 8);  
107:      i2cDataF[1] = dacValue & 0x00FF;  
108:    
109:      //loops until i2cTransmit is ready to send data again  
110:      while (i2cTransmit(0x60, i2cDataF, 2)) {  
111:      }  
112:    
113:      //one bit incremention up to 12 bits (4095)  
114:      /*if (dacValue >= 4095) {  
115:        dacValue = 0;  
116:      } else {  
117:        dacValue += 1;  
118:      }*/  
119:    
120:      //Toggle DAC between max and min value  
121:      if (dacValue == 0xFFF) {  
122:        dacValue = 0;  
123:      } else {  
124:        dacValue = 0xFFF;  
125:      }  
126:    
127:    
128:      //Toggle LED everytime I2C transmission is made  
129:      //Read latch A into ghost register  
130:      GPORTA = LATA;  
131:      //Toggle bit 0  
132:      GPORTA = GPORTA^(1 << 0);  
133:      //Write back into port register  
134:      PORTA = GPORTA;  
135:    
136:    }  
137:    
138:  }  
139:    
140:  //Interrupt service routine  
141:    
142:  interrupt void isr(void) {  
143:    extern int i2cTransmitCycle;  
144:    extern int i2c7bitAddress;  
145:    extern int i2cData[];  
146:    extern int i2cDataCounter;  
147:    extern int i2cDataNoBytes;  
148:    extern int i2cTransmitInProgress;  
149:    
150:    //I2C transmission concists of several interrupt events, variable i2cTransmitCycle is used to step through these events  
151:    //The first interrupt comes with the start condition, SEN, is set.  
152:    if (SSP1IF) {  
153:      //Reset SSP interrupt flag  
154:      SSP1IF = 0;  
155:    
156:      //Send address  
157:      if (i2cTransmitCycle == 1) {  
158:        SSP1BUF = (i2c7bitAddress << 1); //converting 7-bit address to 8-bit write address  
159:      }  
160:    
161:      //Step through and send data in data array  
162:      if (i2cTransmitCycle == 2) {  
163:        if (i2cDataCounter < i2cDataNoBytes) {  
164:          SSP1BUF = i2cData[i2cDataCounter];  
165:          i2cDataCounter += 1;  
166:          i2cTransmitCycle = 1;  
167:        } else {  
168:          i2cTransmitCycle = 3;  
169:        }  
170:      }  
171:    
172:      //Send stop condition  
173:      if (i2cTransmitCycle == 3) {  
174:        PEN = 1;  
175:      }  
176:    
177:      //Stop is complete, ready to transmit again  
178:      if (i2cTransmitCycle == 4) {  
179:        i2cTransmitInProgress = 0;  
180:      }  
181:    
182:      i2cTransmitCycle += 1;  
183:    }  
184:    
185:    
186:    
187:    //If USART receive interrupt is triggered, transmit received symbol  
188:    if (RCIF) {  
189:      TXREG = RCREG;  
190:    }  
191:    
192:    return;  
193:  }  
194:    
195:    
196:  //**************************************************  
197:  //**************Function i2cTransmit****************  
198:  //Takes data array and address of I2C slave*********  
199:  //Sets up appropiate global variables***************  
200:  //Handles transmit in progress flags****************  
201:  //Initializes I2C start condition*******************  
202:  //**************************************************  
203:    
204:  int i2cTransmit(int i2cAddressF, int i2cDataF[], int i2cDataNoBytesF) {  
205:    extern int i2cTransmitInProgress;  
206:    extern int i2c7bitAddress;  
207:    extern int i2cData[];  
208:    extern int i2cDataCounter;  
209:    extern int i2cDataNoBytes;  
210:    
211:    //Just return 1 if I2C transmission is already in progress  
212:    if (i2cTransmitInProgress) {  
213:      return 1;  
214:    }  
215:    
216:    
217:    i2cTransmitInProgress = 1;  
218:    i2cTransmitCycle = 1;  
219:    
220:    i2cTransferDataArray(i2cDataF, i2cDataNoBytesF);  
221:    i2cDataCounter = 0;  
222:    i2cDataNoBytes = i2cDataNoBytesF;  
223:    i2c7bitAddress = i2cAddressF;  
224:    SEN = 1; //Initialize I2C start condition  
225:    
226:    //Don't return function until data is sent and stop condition is initialized  
227:    while (i2cTransmitInProgress) {  
228:    }  
229:    
230:    return 0;  
231:  }  
232:    
233:    
234:  //***********************************************************  
235:  //**************Function i2cTransferDataArray****************  
236:  //Copies data array to global data array for I2C transmission  
237:  //***********************************************************  
238:    
239:  void i2cTransferDataArray(int i2cDataF[], int i2cDataNoBytesF) {  
240:    int i = 0;  
241:    for (i; i < i2cDataNoBytesF; i++) {  
242:      i2cData[i] = i2cDataF[i];  
243:    }  
244:    return;  
245:  }  

No comments:

Post a Comment