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