10 PIC Microcontroller Interview Questions and Answers
Prepare for your next technical interview with this guide on PIC microcontrollers, featuring common questions and detailed answers.
Prepare for your next technical interview with this guide on PIC microcontrollers, featuring common questions and detailed answers.
PIC microcontrollers are a popular choice in embedded systems due to their versatility, low cost, and ease of programming. These microcontrollers are used in a wide range of applications, from consumer electronics to industrial automation, making them a valuable skill set for engineers and developers. With a robust architecture and extensive support from development tools, PIC microcontrollers offer a reliable platform for creating efficient and innovative solutions.
This article provides a curated selection of interview questions designed to test your knowledge and problem-solving abilities with PIC microcontrollers. By working through these questions, you will gain a deeper understanding of key concepts and be better prepared to demonstrate your expertise in technical interviews.
The basic architecture of a PIC microcontroller includes several components:
To configure a GPIO pin as an output and toggle its state every second on a PIC microcontroller, use the following code snippet with MPLAB X IDE and XC8 compiler:
#include <xc.h> // Configuration bits #pragma config FOSC = INTRC_NOCLKOUT #pragma config WDTE = OFF #pragma config PWRTE = OFF #pragma config MCLRE = ON #pragma config CP = OFF #pragma config CPD = OFF #pragma config BOREN = ON #pragma config IESO = OFF #pragma config FCMEN = OFF #pragma config LVP = OFF #define _XTAL_FREQ 4000000 void main(void) { TRISBbits.TRISB0 = 0; // Set RB0 as output while (1) { LATBbits.LATB0 = ~LATBbits.LATB0; // Toggle RB0 __delay_ms(1000); // Delay for 1 second } }
#include <xc.h> // Configuration bits #pragma config FOSC = INTOSCIO #pragma config WDTE = OFF #pragma config PWRTE = OFF #pragma config MCLRE = ON #pragma config CP = OFF #pragma config CPD = OFF #pragma config BOREN = ON #pragma config IESO = OFF #pragma config FCMEN = OFF #pragma config LVP = OFF void __interrupt() ISR() { if (TMR1IF) { TMR1IF = 0; // Clear the interrupt flag TMR1 = 65536 - 1000; // Reload the timer for 1ms } } void main() { T1CON = 0x31; // Timer1 on, prescaler 1:8 TMR1 = 65536 - 1000; // Load the timer for 1ms TMR1IE = 1; // Enable Timer1 interrupt PEIE = 1; // Enable peripheral interrupts GIE = 1; // Enable global interrupts while (1) { // Main loop } }
#include <xc.h> // Configuration bits #pragma config FOSC = INTRC_NOCLKOUT #pragma config WDTE = OFF #pragma config PWRTE = OFF #pragma config MCLRE = ON #pragma config CP = OFF #pragma config CPD = OFF #pragma config BOREN = ON #pragma config IESO = OFF #pragma config FCMEN = OFF #pragma config LVP = OFF void main(void) { PR2 = 0xFF; // Set the PWM period CCPR1L = 0x80; // 50% duty cycle CCP1CONbits.DC1B = 0; CCP1CONbits.CCP1M = 0b1100; // Configure CCP1 for PWM mode T2CONbits.T2CKPS = 0b01; // Prescaler is 4 T2CONbits.TMR2ON = 1; // Enable Timer2 TRISCbits.TRISC2 = 0; // Set PWM pin as output while (1) { // Main loop } }
To send and receive data using UART on a PIC microcontroller, initialize the UART module, configure the baud rate, and implement functions to send and receive data.
Example:
#include <xc.h> // Configuration bits #pragma config FOSC = INTRC_NOCLKOUT #pragma config WDTE = OFF #pragma config PWRTE = ON #pragma config MCLRE = ON #pragma config CP = OFF #pragma config CPD = OFF #pragma config BOREN = ON #pragma config IESO = OFF #pragma config FCMEN = OFF #pragma config LVP = OFF #define _XTAL_FREQ 4000000 void UART_Init(long baud_rate) { unsigned int x; x = (_XTAL_FREQ - baud_rate * 64) / (baud_rate * 64); if (x > 255) { x = (_XTAL_FREQ - baud_rate * 16) / (baud_rate * 16); BRGH = 1; } if (x < 256) { SPBRG = x; } SYNC = 0; SPEN = 1; TRISC7 = 1; TRISC6 = 0; CREN = 1; TXEN = 1; } void UART_Write(char data) { while (!TRMT); TXREG = data; } char UART_Read() { while (!RCIF); return RCREG; } void main() { UART_Init(9600); while (1) { char received = UART_Read(); UART_Write(received); } }
#include <xc.h> #include <stdint.h> #define _XTAL_FREQ 4000000 #define I2C_WRITE 0 #define I2C_READ 1 void I2C_Init(void) { SSPCON = 0b00101000; SSPCON2 = 0; SSPADD = (_XTAL_FREQ / (4 * 100000)) - 1; SSPSTAT = 0; } void I2C_Start(void) { SEN = 1; while (SEN); } void I2C_Stop(void) { PEN = 1; while (PEN); } void I2C_Write(uint8_t data) { SSPBUF = data; while (!SSPIF); SSPIF = 0; } uint8_t I2C_Read(uint8_t ack) { RCEN = 1; while (!SSPIF); SSPIF = 0; uint8_t data = SSPBUF; ACKDT = ack; ACKEN = 1; while (ACKEN); return data; } uint16_t Read_Temperature(void) { uint16_t temperature; I2C_Start(); I2C_Write(0x90 | I2C_WRITE); I2C_Write(0x00); I2C_Start(); I2C_Write(0x90 | I2C_READ); temperature = I2C_Read(0) << 8; temperature |= I2C_Read(1); I2C_Stop(); return temperature; } void main(void) { I2C_Init(); uint16_t temperature = Read_Temperature(); while (1) { // Use the temperature value as needed } }
#include <xc.h> // Configuration bits #pragma config FOSC = HS #pragma config WDTE = OFF #pragma config PWRTE = OFF #pragma config BOREN = ON #pragma config LVP = OFF #pragma config CPD = OFF #pragma config WRT = OFF #pragma config CP = OFF #define CS LATBbits.LATB0 void SPI_Init() { TRISC5 = 0; TRISC4 = 1; TRISC3 = 0; SSPSTAT = 0x40; SSPCON = 0x20; } void SPI_Write(unsigned char data) { SSPBUF = data; while(!SSPSTATbits.BF); } unsigned char SPI_Read() { SSPBUF = 0xFF; while(!SSPSTATbits.BF); return SSPBUF; } void EEPROM_Write(unsigned char address, unsigned char data) { CS = 0; SPI_Write(0x06); CS = 1; __delay_ms(1); CS = 0; SPI_Write(0x02); SPI_Write(address); SPI_Write(data); CS = 1; __delay_ms(5); } unsigned char EEPROM_Read(unsigned char address) { unsigned char data; CS = 0; SPI_Write(0x03); SPI_Write(address); data = SPI_Read(); CS = 1; return data; } void main() { SPI_Init(); EEPROM_Write(0x10, 0x55); unsigned char data = EEPROM_Read(0x10); while(1); }
PIC microcontrollers offer several power management modes to optimize power consumption:
To configure these modes, set specific control registers. For Sleep Mode, use the SLEEP
instruction; for Idle Mode, adjust the OSCCON
register.
To integrate FreeRTOS into a PIC microcontroller project and create a simple task:
Example:
#include <FreeRTOS.h> #include <task.h> void vTaskFunction(void *pvParameters) { for (;;) { // Task code } } int main(void) { // System initialization xTaskCreate(vTaskFunction, "Task 1", 100, NULL, 1, NULL); vTaskStartScheduler(); for (;;); return 0; }
#include <xc.h> // Configuration bits #pragma config FOSC = INTRC_NOCLKOUT #pragma config WDTE = OFF #pragma config PWRTE = OFF #pragma config MCLRE = ON #pragma config CP = OFF #pragma config CPD = OFF #pragma config BOREN = ON #pragma config IESO = OFF #pragma config FCMEN = OFF #pragma config LVP = OFF void RTC_Init() { T1CON = 0x31; // Timer1 with external 32.768 kHz crystal TMR1H = 0x80; // Preload Timer1 for 1 second overflow TMR1L = 0x00; TMR1IF = 0; TMR1IE = 1; PEIE = 1; GIE = 1; } void __interrupt() ISR() { if (TMR1IF) { TMR1IF = 0; TMR1H = 0x80; TMR1L = 0x00; // Increment RTC seconds, minutes, hours, etc. } } void main() { RTC_Init(); while (1) { // Main loop } }