Presentation is loading. Please wait.

Presentation is loading. Please wait.

ECE 3567 Lab 4 Analog-to-Digital Converters

Similar presentations


Presentation on theme: "ECE 3567 Lab 4 Analog-to-Digital Converters"— Presentation transcript:

1 ECE 3567 Lab 4 Analog-to-Digital Converters
Dr. Gregg J Chapman Autumn 2019

2 The Users Manual Chapter 33 REF_A………………………………….pp 858-864
Chapter 34 ADC12_B……………………………..pp

3 Laboratory #4 Goals Implement a TWO channel conversion sequence, one channel for the RC_Voltage (A5), and a second channel for the internal Temperature Sensor (A30). Display the temperature in Fahrenheit on the Liquid Crystal Display. Measure the RC filtered voltage and set the LED color according to voltage values. Display the RC filtered voltage on the Liquid Crystal Display. Configure a Pushbutton to change the LCD display to either temperature or voltage.

4 The RC Circuit P2.1 PWM output RC charging circuit fcutoff = 6 Hz
ADC A5 P2.1 PWM output RC charging circuit A5 input on ADC12

5 The Temperature Sensor

6 LaunchPad LCD Display

7 LaunchPad Pushbuttons

8 Lab #4 Downloaded Files NOTE: Save the RC voltage functions that you wrote last week and add them to the RCMode.c if necessary.

9 void Init_ADC12(void) __interrupt void ADC12_ISR(void)
ADC12.c void Init_ADC12(void) __interrupt void ADC12_ISR(void) Template with declarations and headers is included in the Lab 4 Code Additions download. Copy and ADD all files to your existing project directory.

10 void Init_ADC12(void) ADC12.c

11 ADC12 Initialization Init_ADC12()
Set pin 8.6 as the ANALOG INPUT for A-to-D channel A5 Configure the Internal Voltage Reference. Set up Timer A1 as the ADC SAMPLE CLOCK Activate the internal Temperature Sensor (must ne on ADC12 channel A30) Configure the ADC12 for a 2-channel repeated sequence, beginning with A30 and ending with A5. Set up MEM0 buffer to receive channel A30 data values. Set up MEM1 buffer to receive channel A5 data values. Generate the ADC12 Interrupt whenever MEM1 receives a new conversion value. Clear any pending interrupts, enable interrupts, and start the repeated conversion sequence NOTE: Don’t forget to call Init_ADC12() at the beginning of main().

12 1. Set-up P8.6 as Channel A5 1 1 Tertiary
1 1 Tertiary Note: It is not necessary to set the P8DIR register, bit 6, as an input when you select the A5 (Tertiary) function.

13 2. Configure Internal Voltage Reference

14 2. Configure Internal Voltage Reference
Register – ADC12MCTLx

15 De-Mystifying Voltage Labels
VCC - Positive Voltage, Analog VEE - Negative Voltage (or GND), Analog VDD - Positive Voltage, Digital VSS - Negative Voltage (or GND), Digital

16 3. Set-up Timer A1 as Sample Clock
Clear TA1CTL Select ACLK and No Pre-Divide in TA1CTL

17 3. Set-up Timer A1 as Sample Clock
In TA1CCTL1, Select Compare Mode, Reset/Set Output Mode, Interrupts Disabled

18 3. Set-up Timer A1 as Sample Clock
In TA1CCR0, Set Period for a Frequency of 32 Hz. This gets /8 later for a 4Hz sample rate In TA1CCR1, Set Duty Cycle to 50%

19 3. Set-up Timer A1 as Sample Clock
Start Timer in UP Mode by writing Bits 5-4 to [01]

20 There are FOUR Configuration Registers for the ADC12_B:
4. Activate Internal Temperature Sensor 5. Configure ADC12 for 2-Channel Repeated Sequence There are FOUR Configuration Registers for the ADC12_B: ADC12CTL0 – ADC12CTL3.

21 ADC12 Configuration Register – ADC12CTL0
Set the clock cycles for sample-and-hold for MEM8-MEM23 to 256 (Bits 15-12) 1000

22 ADC12 Configuration Register – ADC12CTL0
Set the clock cycles for sample-and-hold for MEM0-MEM7 to 4 (Bits 11-8) 0000

23 ADC12 Configuration Register – ADC12CTL0
Set Bit 7 to cause the first rising edge of the SHI to initiate sampling and continue automatically Turn on the ADC12 Module (Bit 4)XX1X Disable Conversion (Bit 1)

24 ADC12 Configuration Register – ADC12CTL1
Pre-divide the clock source by 4 (Bit 14-13)

25 ADC12 Configuration Register – ADC12CTL1
Pre-divide the clock source by 4 (Bit 14-13) Select Timer A1 as the clock source by configuring Bits to [100] * * SEE NEXT SLIDE for this incredible example of the inefficiency in the TI documentation!

26 ADC12 Configuration Register – ADC12CTL1
* ADC12SHSx - Select Timer A1 as the clock source by configuring Bits to [100] * This setting depends on which microcontroller model you have. The setting is in a completely different manual for each MCU!! I have placed a copy of the MSP430FR6989.PDF on the course website Page 88 = 0x100

27 ADC12 Configuration Register – ADC12CTL1
Pre-divide the clock source by 4 (Bit 14-13) Select Timer A1 as the clock source by configuring Bits to [100] * Configure the ADC12_B clock divider to 2 (Bits 7-5)

28 ADC12 Configuration Register – ADC12CTL1
Pre-divide the clock source by 4 (Bit 14-13) Select Timer A1 as the clock source by configuring Bits to [100] * Configure the ADC12_B clock divider to 2 (Bits 7-5) Configure Bits 4-3 to select ACLK as the source clock

29 ADC12 Configuration Register – ADC12CTL1
Pre-divide the clock source by 4 (Bit 14-13) Select Timer A1 as the clock source by configuring Bits to [100] * Configure the ADC12_B clock divider to 2 (Bits 7-5) Configure Bits 4-3 to select ACLK as the source clock Select the Repeated-Sequence-of-Channels option for Bits 2-1

30 ADC12 Configuration Register – ADC12CTL2
This register controls bit resolution and data readback format. There are no changes from the default values in this register

31 ADC12 Configuration Register – ADC12CTL3
1. Set Bit 7. This selects the Temperature Sensor for ADC channel A30

32 6. Set MEM0 Buffer for A30 Data
Register – ADC12MCTL0 Disable the Comparator Window Enable Single-ended Mode

33 6. Set MEM0 Buffer for A30 Data
Register – ADC12MCTL0 Set voltage source combination to VR+ = VREF buffered, VR- = AVSS

34 6. Set MEM0 Buffer for A30 Data
Register – ADC12MCTL0 MEM0 is NOT the end of the sequence

35 6. Set MEM0 Buffer for A30 Data
Register – ADC12MCTL0 Select A30 (the temperature probe) as the Input Source.

36 7. Set MEM1 Buffer for A5 Data
Register – ADC12MCTL1 Disable the Comparator Window Enable Single-ended Mode

37 7. Set MEM1 Buffer for A5 Data
Register – ADC12MCTL1 Set voltage source combination to VR+ = AVCC, VR- = AVSS

38 7. Set MEM1 Buffer for A5 Data
Register – ADC12MCTL1 MEM1 IS the end of the sequence

39 7. Set MEM1 Buffer for A5 Data
Register – ADC12MCTL1 Select A5 as the Input Source.

40 9a. Clear Interrupts (write 0)

41 8. Generate the ADC12 Interrupt whenever MEM1 receives a new conversion value.
9b. Enable Interrupts

42 9c. Enable Conversion

43 Please have your Init_ADC12() checked before proceeding
Checkpoint #1 Please have your Init_ADC12() checked before proceeding

44 ADC12 Configuration – Interrupt Service Routine
In the ADC12 Interrupt Service Routine, for the ADCMEM1 interrupt case: a. Clear the Interrupt: ADC12_B_clearInterrupt(ADC12_B_BASE, 0, ADC12_B_IFG1); b. Transfer MEM0 and MEM1 values to the following variables: ADCValue0 = ADC12MEM0; ADCValue1 = ADC12MEM1; 2. Comment out the #pragma for the Timer A1 vector and the ADC12 vector

45 Interrupt Service Routine
The ADC12 Interrupt Service Routine

46 ADC12 Configuration – Don’t forget to comment out used #pragmas in unused_interrupts.c

47 TempSensorMode.c

48 TempSensorMode.c Functions

49 TempSensorMode.c Functions

50 TempSensorMode.c Functions
void displayTemp() { clearLCD(); if (tempUnit == 0) showChar('C',pos6); } else showChar('F',pos6); // Handles displaying up to degrees if (deg>=1000) showChar((deg/1000)%10 + '0',pos3); if (deg>=100) showChar((deg/100)%10 + '0',pos4); if (deg>=10) showChar((deg/10)%10 + '0',pos5); // Degree symbol LCDMEM[pos5+1] |= 0x04; //Uses Modulo Division to get Remainder // then adds 48 (‘0’) to convert to ASCII // One decimal place at a time

51 myLcd.c

52 LaunchPad LCD Display

53 myLcd.c Character Maps }; // LCD memory map for uppercase letters
const char alphabetBig[26][2] = { {0xEF, 0x00}, /* "A" LCD segments a+b+c+e+f+g+m */ {0xF1, 0x50}, /* "B" */ {0x9C, 0x00}, /* "C" */ {0xF0, 0x50}, /* "D" */ {0x9F, 0x00}, /* "E" */ {0x8F, 0x00}, /* "F" */ {0xBD, 0x00}, /* "G" */ {0x6F, 0x00}, /* "H" */ {0x90, 0x50}, /* "I" */ {0x78, 0x00}, /* "J" */ {0x0E, 0x22}, /* "K" */ {0x1C, 0x00}, /* "L" */ {0x6C, 0xA0}, /* "M" */ {0x6C, 0x82}, /* "N" */ {0xFC, 0x00}, /* "O" */ {0xCF, 0x00}, /* "P" */ {0xFC, 0x02}, /* "Q" */ {0xCF, 0x02}, /* "R" */ {0xB7, 0x00}, /* "S" */ {0x80, 0x50}, /* "T" */ {0x7C, 0x00}, /* "U" */ {0x0C, 0x28}, /* "V" */ {0x6C, 0x0A}, /* "W" */ {0x00, 0xAA}, /* "X" */ {0x00, 0xB0}, /* "Y" */ {0x90, 0x28} /* "Z" */ }; // LCD memory map for numeric digits const char digit[10][2] = { {0xFC, 0x28}, /* "0" LCD segments a+b+c+d+e+f+k+q */ {0x60, 0x20}, /* "1" */ {0xDB, 0x00}, /* "2" */ {0xF3, 0x00}, /* "3" */ {0x67, 0x00}, /* "4" */ {0xB7, 0x00}, /* "5" */ {0xBF, 0x00}, /* "6" */ {0xE4, 0x00}, /* "7" */ {0xFF, 0x00}, /* "8" */ {0xF7, 0x00} /* "9" */ };

54 myLcd.c Functions void Init_LCD() { LCD_C_initParam initParams = {0};
initParams.clockSource = LCD_C_CLOCKSOURCE_ACLK; initParams.clockDivider = LCD_C_CLOCKDIVIDER_1; initParams.clockPrescalar = LCD_C_CLOCKPRESCALAR_16; initParams.muxRate = LCD_C_4_MUX; initParams.waveforms = LCD_C_LOW_POWER_WAVEFORMS; initParams.segments = LCD_C_SEGMENTS_ENABLED; LCD_C_init(LCD_C_BASE, &initParams); // LCD Operation - VLCD generated internally, V2-V4 generated internally, v5 to ground LCD_C_setPinAsLCDFunctionEx(LCD_C_BASE, LCD_C_SEGMENT_LINE_0, LCD_C_SEGMENT_LINE_21); LCD_C_setPinAsLCDFunctionEx(LCD_C_BASE, LCD_C_SEGMENT_LINE_26, LCD_C_SEGMENT_LINE_43); LCD_C_setVLCDSource(LCD_C_BASE, LCD_C_VLCD_GENERATED_INTERNALLY, LCD_C_V2V3V4_GENERATED_INTERNALLY_NOT_SWITCHED_TO_PINS, LCD_C_V5_VSS); // Set VLCD voltage to 3.20v LCD_C_setVLCDVoltage(LCD_C_BASE, LCD_C_CHARGEPUMP_VOLTAGE_3_02V_OR_2_52VREF); // Enable charge pump and select internal reference for it LCD_C_enableChargePump(LCD_C_BASE); LCD_C_selectChargePumpReference(LCD_C_BASE, LCD_C_INTERNAL_REFERENCE_VOLTAGE); LCD_C_configChargePump(LCD_C_BASE, LCD_C_SYNCHRONIZATION_ENABLED, 0); // Clear LCD memory LCD_C_clearMemory(LCD_C_BASE); //Turn LCD on LCD_C_on(LCD_C_BASE); }

55 myLcd.c Functions void showChar(char c, int position) { if (c == ' ')
// Display space LCDMEM[position] = 0; LCDMEM[position+1] = 0; } else if (c >= '0' && c <= '9') // Display digit LCDMEM[position] = digit[c-48][0]; LCDMEM[position+1] = digit[c-48][1]; else if (c >= 'A' && c <= 'Z') // Display alphabet LCDMEM[position] = alphabetBig[c-65][0]; LCDMEM[position+1] = alphabetBig[c-65][1]; else // Turn all segments on if character is not a space, digit, or uppercase letter LCDMEM[position] = 0xFF; LCDMEM[position+1] = 0xFF;

56 myLcd.c Functions /* * Clears memories to all 6 digits on the LCD */
void clearLCD() { LCDMEM[pos1] = LCDBMEM[pos1] = 0; LCDMEM[pos1+1] = LCDBMEM[pos1+1] = 0; LCDMEM[pos2] = LCDBMEM[pos2] = 0; LCDMEM[pos2+1] = LCDBMEM[pos2+1] = 0; LCDMEM[pos3] = LCDBMEM[pos3] = 0; LCDMEM[pos3+1] = LCDBMEM[pos3+1] = 0; LCDMEM[pos4] = LCDBMEM[pos4] = 0; LCDMEM[pos4+1] = LCDBMEM[pos4+1] = 0; LCDMEM[pos5] = LCDBMEM[pos5] = 0; LCDMEM[pos5+1] = LCDBMEM[pos5+1] = 0; LCDMEM[pos6] = LCDBMEM[pos6] = 0; LCDMEM[pos6+1] = LCDBMEM[pos6+1] = 0; LCDM14 = LCDBM14 = 0x00; LCDM18 = LCDBM18 = 0x00; LCDM3 = LCDBM3 = 0x00; // LCDMEM[12] = LCDMEM[13] = 0; }

57 myLcd.c Functions

58 Quiz Question What number do you subtract from the ASCII character for a number to convert from ASCII code to an actual numeric value? What is the number in Hexadecimal? What is the number in Decimal? What ASCII number can you subtract from another ASCII number to convert it to a decimal value? What do you add to a number to convert to the ASCII character?

59 TempSensorMode.c Functions
void displayTemp() { clearLCD(); if (tempUnit == 0) showChar('C',pos6); } else showChar('F',pos6); // Handles displaying up to degrees if (deg>=1000) showChar((deg/1000)%10 + '0',pos3); if (deg>=100) showChar((deg/100)%10 + '0',pos4); if (deg>=10) showChar((deg/10)%10 + '0',pos5); // Degree symbol LCDMEM[pos5+1] |= 0x04; //Uses Modulo Division to get Remainder // then adds 48 (‘0’) to convert to ASCII // One decimal place at a time

60 Checkpoint #2 Demonstrate the temperature sensor on the LCD (display) in Fahrenheit with 16 averages and updating once every second. You may use the cold spray to change the temperature rapidly.

61 RCMode.c

62 RCMode.c void RC_Voltage() { ISR_Flag = 0;
// Calculate voltage from A5 ADC data unsigned int tempRC = (ADCValue1); tempRC = ((((unsigned long)tempRC)*4/5) + 28); // Averaging Routine k2++; sum2 = sum2 + tempRC; if(k2 >= Vsize) // Vsize is the number of values to average. In 3567.h volts = sum2/(Vsize); sum2 = 0; k2 = 0; // Display Voltage if(LCD_Control == TRUE) displayVolts(); }

63 RCMode.c

64 Checkpoint #3 Demonstrate the filtered RC voltage with 2 digits after the decimal, an average of 16 value, and updating once per second.

65 Update the main() Initializations
//*********************The Initializations*************************************/ Init_LCD(); Init_GPIO(); Init_Clocks(); Init_PWM(); // This was written for you and should be in TempSensorMode.c tempSensorModeInit(); // Given. Add this. Init_ADC12(); // New. You write this Init_RC(); // You wrote this last week Init_LCD(); // Given. Add this.

66 Pushbutton Bounce Software must require button to remain in a stable logic state for at least the duration of a worst case observed for switch bounce. Multiple transitions causes many state changes or PB Interrupts. Use multiple pin reads and a counter to verify that the logic level of the button has remained stable for the debounce duration. Measure worst case with oscilloscope Use delays, with or without ISR, to verify bounce duration has ended. 6 mS Transition Verified INTERRUPTS

67 Pushbutton Code Use BOTH pushbuttons. One to change the LCD to RC_Voltage and the other pushbutton to change the LCD to display temperature. Clear the LED and LCD when either button is pressed and held. Use the Booleans RC_Control and T_Control to select which process is displayed. if(Temp_Button_Press >=5) // Detect 500 mSec button press. { RC_Control= FALSE; T_Control = TRUE; PWM_null(); // Turn off LED clearLCD(); // Clear out LCD Temp_Button_Press = 0; Volt_Button_Press = 0; while((P1IN & BIT1) == 0x00); } else if(Volt_Button_Press >=5) RC_Control= TRUE; T_Control = FALSE; while((P1IN & BIT2) == 0x00);

68 Pushbutton Code “Debounce” the button press by delaying action for 500 milliseconds. Note that this is 5 executions of the Timer A0 ISR.

69 Pushbutton Code Comment out the Interrupt configurations for P1.1 and P1.2 in Init_GPIO():

70 Pushbutton Code IN unused_interrupts.c, make sure the #pragma vector = PORT1_VECTOR // Port 1 is NOT commented out 7. Configure BOTH pushbuttons as INPUTS with PULL_UP Resistors at the beginning of main(): P1DIR &= ~BIT1; // Set as Input P1REN |= BIT1; // Configure Pull-up Resistor P1OUT |= BIT1; // Completes Pull-up Configuration NOTE: No Pull-up Rs here unless configured!

71 Pushbutton Code Polling Method
8. Modify main() to conditionally execute the RC voltage or Temperature Measurement using Booleans. Toggle the two control Booleans in main if the pushbutton is pressed. e.g.: if(RC_Control == TRUE) // Change PWM, measure voltage and display color range { update_RC(); RC_Voltage(); update_RGB(); } else if(T_Control == TRUE) // Temperature in Fahrenheit on displayed on LCD tempSensor();

72 If-else for LED Color Add if-else code to update_RGB() change the LED color every 500 mV. The voltage should be calculated from the AVERAGED A5 A-to-D value. This variable is called volts Use the following table: COLOR Voltage Range Min Voltage (mV) Max Voltage (mV) RED 500 ORANGE 501 1000 YELLOW 1001 1500 GREEN 1501 2000 BLUE 2001 2500 PURPLE 2501 3000 WHITE > 3000 NA

73 Checkpoint #4 and #5 #4 - Demonstrate that the two pushbuttons select either the RC_Voltage or the Temperature (F) function. The LED and LCD should remain off if either button is pressed and held. #5 - In the RC_Voltage mode, demonstrate that the LED changes color based on the filtered RC voltage according to the table provided.


Download ppt "ECE 3567 Lab 4 Analog-to-Digital Converters"

Similar presentations


Ads by Google