AVR1631 - Energy Meter Reference Design with ATxmega32A4  Rev 1.0
 All Data Structures Files Functions Variables Typedefs Macros
meter_initialisation.c
Go to the documentation of this file.
1 /* This file has been prepared for Doxygen automatic documentation generation.*/
49 #include "meter.h"
50 
52 __eeprom struct coefficient eeprom_t @ 0x12;
53 struct coefficient meter_t;
54 
59 void delay_ms(uint16_t ms)
60 {
61  int x = 0;
62  for (x=0;x<=ms;x++)
63  {
64  delay_us(1000);
65  }
66 }
67 
68 /* brief This function initialise the LCD Module
69 *
70 */
71 void init_lcd(void)
72 {
73  LCD.DIRSET = LCD_CS | LCD_WRITE | LCD_DATA | LCD_READ;
74  LCD.PIN3CTRL = PORT_OPC_PULLUP_gc;
75  LCD.PIN2CTRL = PORT_OPC_PULLUP_gc;
76  LCD.PIN1CTRL = PORT_OPC_PULLUP_gc;
77  LCD.PIN0CTRL = PORT_OPC_PULLUP_gc;
78  LCD_CS_SET;
79  LCD_WRITE_SET;
80  LCD_DATA_SET;
81  LCD_READ_SET;
82  lcd_command(LCD_COMMAND,0x01); //sys en
83  delay_us(100);
84  lcd_command(LCD_COMMAND,0x29); //bias 1/3, 10:4
85  delay_us(100);
86  lcd_command(LCD_COMMAND,0xE3); //normal mode
87  delay_us(100);
88  lcd_command(LCD_COMMAND,0x03); //LCD on
89 }
90 
91 
92 
98 void clock_init(void)
99 {
101  CLKSYS_Enable( OSC_RC32MEN_bm );
102  CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc );
103  do {} while ( CLKSYS_IsReady( OSC_RC32MRDY_bm ) == 0 );
104  CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_RC32M_gc );
105  CLKSYS_Disable( OSC_RC2MEN_bm | OSC_RC32KEN_bm | OSC_PLLEN_bm);
106  delay_ms(1);
107 
109  OSC.XOSCCTRL = OSC_XOSCSEL_32KHz_gc; //0x02;
110  CLKSYS_Enable(OSC_XOSCEN_bm);
111  do {} while ( CLKSYS_IsReady( OSC_XOSCRDY_bm ) == 0 );
112  OSC.DFLLCTRL = ( OSC.DFLLCTRL & ~(OSC_RC32MCREF_gm | OSC_RC2MCREF_bm)) | OSC_RC32MCREF0_bm;
113  DFLLRC32M.CTRL = DFLL_ENABLE_bm;
114  delay_ms(1);
115 }
116 
120 void init_ioport(void)
121 {
122 
130  PORTB.DIRCLR = PIN2_bm;
131  PORTB.DIRSET = TAMPER_CURRENT_REVERSAL | TAMPER_EARTH_FAULT | TAMPER_NEUTRAL_CUT;
132  PORTB.PIN2CTRL = PORT_OPC_PULLUP_gc;
133  PORTB.PIN2CTRL = PORT_ISC_FALLING_gc ;
134  PORTB.OUTCLR = PIN0_bm | PIN1_bm | PIN2_bm | PIN3_bm;
135  PORTB.INT0MASK = PIN2_bm;
136  PORTB.INTCTRL = PORT_INT0LVL_LO_gc;
137 
148  PORTC.DIRCLR = PIN0_bm | PIN1_bm |PIN2_bm |PIN3_bm |PIN4_bm | PIN5_bm;
149  PORTC.PIN0CTRL = PORT_OPC_PULLUP_gc;
150  PORTC.PIN1CTRL = PORT_OPC_PULLUP_gc;
151  PORTC.PIN2CTRL = PORT_OPC_PULLUP_gc;
152  PORTC.PIN2CTRL |= PORT_ISC_FALLING_gc;
153  PORTC.PIN3CTRL = PORT_OPC_PULLUP_gc;
154  PORTC.PIN4CTRL = PORT_OPC_PULLUP_gc;
155  PORTC.PIN4CTRL |= PORT_ISC_RISING_gc;
156  PORTC.PIN5CTRL = PORT_OPC_PULLUP_gc;
157  PORTC.PIN5CTRL |= PORT_ISC_FALLING_gc;
158  PORTC.OUTCLR = PIN2_bm |PIN3_bm |PIN4_bm | PIN5_bm;
159  PORTC.INT0MASK = PIN2_bm |PIN4_bm |PIN5_bm;
160  PORTC.INTCTRL = PORT_INT0LVL_LO_gc;
161 
172  PORTD.DIRSET = PIN0_bm | PIN1_bm | PIN3_bm;
173  PORTD.DIRCLR = PIN2_bm | PIN4_bm | PIN5_bm | PIN6_bm | PIN7_bm;
174  PORTD.PIN0CTRL = PORT_OPC_PULLUP_gc;
175  PORTD.PIN1CTRL = PORT_OPC_WIREDANDPULL_gc;
176  PORTD.PIN2CTRL = PORT_ISC_BOTHEDGES_gc;
177  PORTD.PIN2CTRL |= PORT_OPC_PULLDOWN_gc;
178  PORTD.PIN2CTRL |= PORT_SRLEN_bm;
179  PORTD.PIN3CTRL = PORT_OPC_PULLUP_gc;
180  PORTD.PIN4CTRL = PORT_OPC_WIREDANDPULL_gc;
181  PORTD.PIN5CTRL = PORT_OPC_PULLUP_gc;
182  PORTD.PIN6CTRL = PORT_OPC_PULLUP_gc;
183  PORTD.PIN7CTRL = PORT_OPC_PULLUP_gc;
184  PORTD.INT0MASK = PIN2_bm;
185  PORTD.INTCTRL = PORT_INT0LVL_HI_gc;
186  PORTD.OUTCLR = PIN0_bm | PIN1_bm | PIN3_bm | PIN4_bm;
187 }
188 
192 void init_UART(void)
193 {
195  USART_PORT.DIRSET = PIN7_bm;
196  USART_PORT.DIRCLR = PIN6_bm;
197 
200  USART.CTRLC = (uint8_t) UART_CHARACTER_SIZE | UART_PARITY_MODE_SIZE | false;
201 
203  USART.BAUDCTRLA = UART_BSEL_VALUE;
204 
206  USART.CTRLB |= USART_RXEN_bm;
207  USART.CTRLB |= USART_TXEN_bm;
208 
209  USART.CTRLA = USART_RXCINTLVL0_bm;
210 }
211 
212 
218 void init_eeprom(void)
219 {
220  for(uint8_t j = 0; j < 7; j++)
221  {
222  meter.watt_const[j] = eeprom.watt_const[j];
223  meter.shunt_const[j] = eeprom.shunt_const[j];
224  meter.shunt_offset[j] = eeprom.shunt_offset[j];
225  meter.watt_offset[j] = eeprom.watt_offset[j];
226  meter.A1[j] = eeprom.A1[j];
227  meter.B1[j] = eeprom.B1[j];
228  }
229  meter.volt_const = eeprom.volt_const;
230  meter.kwh = eeprom.kwh;
231 }
232 
238 {
239  PR.PRGEN = PR_USB_bm | PR_AES_bm | PR_EBI_bm | PR_EVSYS_bm | PR_DMA_bm;
240  PR.PRPA = PR_DAC_bm | PR_AC_bm;
241  PR.PRPB = PR_DAC_bm | PR_AC_bm | PR_ADC_bm;
242  PR.PRPC = PR_TWI_bm | PR_USART0_bm | PR_SPI_bm | PR_HIRES_bm | PR_TC0_bm;
243  PR.PRPD = PR_TWI_bm | PR_USART0_bm | PR_USART1_bm | PR_SPI_bm | PR_HIRES_bm | PR_TC1_bm;
244  PR.PRPE = PR_TWI_bm | PR_USART0_bm | PR_USART1_bm | PR_SPI_bm | PR_HIRES_bm | PR_TC1_bm;
245  PR.PRPF = PR_TWI_bm | PR_USART0_bm | PR_USART1_bm | PR_SPI_bm | PR_HIRES_bm | PR_TC1_bm;
246 }
247 
248 
253 void init_timer(void)
254 {
255  TCC1.PER = F_SAMPLING;
256  TCC1.CTRLA = ( TCC1.CTRLA & ~TC1_CLKSEL_gm ) | TC_CLKSEL_DIV64_gc;
257  TCC1.CTRLB = (TCC1.CTRLB & ~TC1_WGMODE_gm);
258  TCC1.INTCTRLA = (TCC1.INTCTRLA & ~(TC1_OVFINTLVL_gm | TC1_ERRINTLVL_gm))|TC1_OVFINTLVL0_bm;
259  SLEEP.CTRL = (SLEEP.CTRL & ~SLEEP_SMODE_gm)| SLEEP_SMODE_IDLE_gc;
260 
261  TCE0.PER = 0xFFFF;
262  TCE0.CNT = 0;
263  TCE0.CTRLA = ( TCE0.CTRLA & ~TC0_CLKSEL_gm ) | TC_CLKSEL_DIV64_gc;
264  TCE0.CTRLB = (TCE0.CTRLB & ~TC0_WGMODE_gm);
265 }
266 
271 void init_ADC()
272 {
274  ADC_ConvMode_and_Resolution_Config(&ADCA, ADC_ConvMode_Signed, ADC_RESOLUTION_12BIT_gc);
275 
277  ADC_Prescaler_Config(&ADCA, ADC_PRESCALER_DIV128_gc);
278 
280  ADC_Reference_Config(&ADCA, ADC_REFSEL_INT1V_gc);
281 
282  ADC_Low_Impedance_Mode(&ADCA);
283 
288  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
289  ADC_CH_GAIN_32X_gc);
290  gain_stage = 0;
291  offset_cnt = 5;
292 
294  ADC_Ch_InputMux_Config(&ADCA.CH0, ADC_CH_MUXPOS_PIN0_gc, ADC_CH_MUXNEG_PIN4_gc);
295 
297  ADC_Ch_Interrupts_Config(&ADCA.CH0, ADC_CH_INTMODE_COMPLETE_gc, ADC_CH_INTLVL_MED_gc);
299 
300 
301 
306  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
307  ADC_CH_GAIN_2X_gc);
309  ADC_Ch_InputMux_Config(&ADCA.CH1, ADC_CH_MUXPOS_PIN1_gc, ADC_CH_MUXNEG_PIN5_gc);
310 
312  ADC_Ch_Interrupts_Config(&ADCA.CH1, ADC_CH_INTMODE_COMPLETE_gc, ADC_CH_INTLVL_MED_gc);
313 
314 
316 
321  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
322  ADC_CH_GAIN_2X_gc);
323 
325  ADC_Ch_InputMux_Config(&ADCA.CH2, ADC_CH_MUXPOS_PIN2_gc, ADC_CH_MUXNEG_PIN6_gc);
326 
328  ADC_Ch_Interrupts_Config(&ADCA.CH2, ADC_CH_INTMODE_COMPLETE_gc, ADC_CH_INTLVL_MED_gc);
329 
330 
332 
333  //*************** ADC Channel 3 *************************************/
335  // Setup channel 1 to have diff gain input.
337  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
338  ADC_CH_GAIN_2X_gc);
339 
340  // Set input to the channels in ADC A to be PIN 0 and PIN 4.
341  ADC_Ch_InputMux_Config(&ADCA.CH3, ADC_CH_MUXPOS_PIN3_gc, ADC_CH_MUXNEG_PIN7_gc);
342 
343  // Enable low level interrupts on ADCA channel 0, on conversion complete.
344  //ADC_Ch_Interrupts_Config(&ADCA.CH3, ADC_CH_INTMODE_COMPLETE_gc, ADC_CH_INTLVL_LO_gc);
345 
346 //***********************************************************************/
347 
348 
350  PMIC.CTRL |= (PMIC_LOLVLEX_bm | PMIC_MEDLVLEX_bm |PMIC_RREN_bm);
351 
353  sei();
354 
355  ADC_Pipeline_Flush(&ADCA);
356 
358  ADC_Enable(&ADCA);
359 
362  ADC_Wait_32MHz(&ADCA);
364  meter_flush();
365 
366  PORTA.DIRCLR = PIN3_bm | PIN7_bm;
367  PORTA.PIN3CTRL = PORT_OPC_PULLUP_gc;
368  PORTA.PIN7CTRL = PORT_OPC_PULLUP_gc;
369 }
370 
371 
372 
378 {
379  /* Set up ADC A to have signed conversion mode and 12 bit resolution. */
380  ADC_ConvMode_and_Resolution_Config(&ADCA, ADC_ConvMode_Signed, ADC_RESOLUTION_12BIT_gc);
381 
382  /* Set sample rate */
383  ADC_Prescaler_Config(&ADCA, ADC_PRESCALER_DIV128_gc);
384 
385  /* Set referance voltage on ADC A to be VCC/1.6 V.*/
386  ADC_Reference_Config(&ADCA, ADC_REFSEL_INT1V_gc);
387 
388  /* Get offset value for ADC A. */
390  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
391  ADC_CH_GAIN_1X_gc);
392 
393  ADC_Ch_InputMux_Config(&ADCA.CH0, ADC_CH_MUXPOS_PIN4_gc, ADC_CH_MUXNEG_PIN4_gc);
394 
395  ADC_Enable(&ADCA);
396  /* Wait until common mode voltage is stable. Default clk is 32MHz and
397  * therefore below the maximum frequency to use this function. */
398  ADC_Wait_32MHz(&ADCA);
399  offset[0] = ADC_Offset_Get_Signed(&ADCA, &ADCA.CH0, true);
400 
401  delay_us(1000);
403  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
404  ADC_CH_GAIN_2X_gc);
405  delay_us(1000);
406  offset[1] = ADC_Offset_Get_Signed(&ADCA, &ADCA.CH0, true);
407 
408 
409  delay_us(1000);
411  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
412  ADC_CH_GAIN_4X_gc);
413  delay_us(1000);
414  offset[2] = ADC_Offset_Get_Signed(&ADCA, &ADCA.CH0, true);
415 
416 
417  delay_us(1000);
419  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
420  ADC_CH_GAIN_8X_gc);
421  delay_us(1000);
422  offset[3] = ADC_Offset_Get_Signed(&ADCA, &ADCA.CH0, true);
423 
424 
425  delay_us(1000);
427  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
428  ADC_CH_GAIN_16X_gc);
429  delay_us(1000);
430  offset[4] = ADC_Offset_Get_Signed(&ADCA, &ADCA.CH0, true);
431 
432 
433  delay_us(1000);
435  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
436  ADC_CH_GAIN_32X_gc);
437  delay_us(1000);
438  offset[5] = ADC_Offset_Get_Signed(&ADCA, &ADCA.CH0, true);
439 
440  delay_us(1000);
442  ADC_CH_INPUTMODE_DIFFWGAIN_gc,
443  ADC_CH_GAIN_64X_gc);
444  delay_us(1000);
445  offset[6] = ADC_Offset_Get_Signed(&ADCA, &ADCA.CH0, true);
446 
447  ADC_Disable(&ADCA);
448 
449 }
450 
456 {
457  // Pullup on all ports, to ensure a defined state.
458  PORTCFG.MPCMASK = 0xFF;
459  PORTA.PIN0CTRL = PORT_OPC_PULLUP_gc;
460  PORTA.DIRCLR = 0xFF;
461 
462  PORTCFG.MPCMASK = 0x0F;
463  PORTB.PIN0CTRL = PORT_OPC_PULLUP_gc;
464  PORTB.DIRCLR = 0x0F;
465 
466  PORTCFG.MPCMASK = ~PIN2_bm;
467  PORTC.PIN0CTRL = PORT_OPC_PULLUP_gc;
468  PORTC.DIRCLR = 0xFF;
469 
470  PORTCFG.MPCMASK = ~(PIN2_bm | PIN4_bm);
471  PORTD.PIN0CTRL = PORT_OPC_PULLUP_gc;
472  PORTD.DIRCLR = 0xFF;
473 
474  PORTCFG.MPCMASK = 0x0F;
475  PORTE.PIN0CTRL = PORT_OPC_PULLUP_gc;
476  PORTE.DIRCLR = 0x0F;
477 }
478