0% found this document useful (0 votes)
1 views6 pages

Write c Program File

The document contains a C program for controlling a BLDC motor using a PIC microcontroller. It includes functions for initialization, ADC, PWM, and commutation logic, structured for easy editing and compilation. The main loop manages motor control based on ADC readings and zero-cross detection.

Uploaded by

kripushpa0210
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views6 pages

Write c Program File

The document contains a C program for controlling a BLDC motor using a PIC microcontroller. It includes functions for initialization, ADC, PWM, and commutation logic, structured for easy editing and compilation. The main loop manages motor control based on ADC readings and zero-cross detection.

Uploaded by

kripushpa0210
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Write c program file

Here is the extracted C program from your [Link] file. It is structured for BLDC motor
control using a PIC microcontroller, including all major functions and definitions for initialization,
ADC, PWM, commutation logic, and the main loop. You can use this in a ".c" file for further
editing or compilation. [1]

#include <xc.h>
#include <stdint.h>
#include <stdbool.h>

#define _XTAL_FREQ 20000000UL

#pragma config FOSC = HS


#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF

#define PWM_A_H RC2


#define PWM_B_H RC1
#define PWM_C_H RD0
#define PWM_A_L RB0
#define PWM_B_L RB1
#define PWM_C_L RB2

#define ADC_POT_CH 0
#define ADC_PHASE_U 1
#define ADC_PHASE_V 2
#define ADC_PHASE_W 3

#define PWM_PERIOD 250


#define BLANK_US 200
#define ZERO_THRESHOLD 8
#define ADVANCE_US 150
#define STARTUP_STEPS 100
#define SOFT_PWM_PIN_LAT LATD

volatile uint8_t comm_step = 0;


volatile uint16_t pwmDuty = 100;
volatile bool adcSampleReady = false;
volatile uint8_t floatingPhase = 0;
volatile bool gotZeroCross = false;
volatile uint16_t blankTimerTicks = 0;
volatile uint16_t advanceTimerTicks = 0;
volatile bool advancePending = false;
volatile uint16_t startupCounter = 0;
volatile bool openLoop = true;

void io_init(void);
void adc_init(void);
uint16_t adc_read(uint8_t ch);
void pwm_init(void);
void setDuty(uint16_t d);
void commutate(uint8_t step);
void startBlanking(void);
void enablePWMOutputs(bool en);

#define TMR0_TICK_US 50UL

void main(void)
{
io_init();
adc_init();
pwm_init();
setDuty(pwmDuty);
enablePWMOutputs(true);
comm_step = 0;
commutate(comm_step);

while (1)
{
uint16_t pot = adc_read(ADC_POT_CH);
uint16_t newDuty = (pot * PWM_PERIOD) / 1023;
pwmDuty = newDuty;
setDuty(pwmDuty);

if (gotZeroCross && !openLoop)


{
gotZeroCross = false;
advancePending = true;
advanceTimerTicks = (ADVANCE_US + TMR0_TICK_US - 1) / TMR0_TICK_US;
}

if (openLoop)
{
__delay_ms(10);
startupCounter++;
if (startupCounter >= STARTUP_STEPS)
{
openLoop = false; // try to switch to sensorless
}
else
{
comm_step = (comm_step + 1) % 6;
commutate(comm_step);
startBlanking();
}
}
__delay_ms(1);
}
}

void io_init(void)
{
ADCON1 = 0x80;
ADCON1 = 0x08;
TRISA = 0xFF;
TRISB = 0x00;
TRISC = 0x00;
TRISD = 0x0E;
TRISE = 0x00;
PORTB = 0x00;
PORTC = 0x00;
PORTD = 0x00;
PORTE = 0x00;
}

void adc_init(void)
{
ADCON0 = 0x01;
ADCON1 = 0x0A;
__delay_ms(2);
}

uint16_t adc_read(uint8_t ch)


{
ADCON0 &= 0xC7;
ADCON0 |= (ch << 3);
__delay_us(20);
GO_nDONE = 1;
while (GO_nDONE);
return ((ADRESH << 8) | ADRESL);
}

void pwm_init(void)
{
PR2 = PWM_PERIOD;
T2CON = 0x04;
CCP1CON = 0x0C;
CCP2CON = 0x0C;
OPTION_REG = 0x07;
INTCON = 0;
TMR0 = 0;
INTCONbits.TMR0IE = 1;
INTCONbits.TMR0IF = 0;
[Link] = 1;
}

void setDuty(uint16_t d)
{
if (d > PWM_PERIOD) d = PWM_PERIOD;
CCPR1L = (uint8_t)(d >> 2);
CCP1CON &= 0xCF;
CCP1CON |= ( (d & 0x03) << 4 );
CCPR2L = (uint8_t)(d >> 2);
CCP2CON &= 0xCF;
CCP2CON |= ( (d & 0x03) << 4 );
}

void enablePWMOutputs(bool en)


{
(void)en;
}

void commutate(uint8_t step)


{
PWM_A_H = 0; PWM_A_L = 0;
PWM_B_H = 0; PWM_B_L = 0;
PWM_C_H = 0; PWM_C_L = 0;

switch (step % 6) {
case 0:
PWM_A_L = 0;
PWM_A_H = 1;
PWM_B_L = 1;
PWM_B_H = 0;
PWM_C_L = 0; PWM_C_H = 0;
floatingPhase = ADC_PHASE_W;
break;
case 1:
PWM_C_H = 1;
PWM_B_L = 1;
PWM_A_H = 0; PWM_A_L = 0;
floatingPhase = ADC_PHASE_U;
break;
case 2:
PWM_C_H = 1;
PWM_A_L = 1;
PWM_B_H = 0; PWM_B_L = 0;
floatingPhase = ADC_PHASE_V;
break;
case 3:
PWM_B_H = 1;
PWM_A_L = 1;
PWM_C_H = 0; PWM_C_L = 0;
floatingPhase = ADC_PHASE_W;
break;
case 4:
PWM_B_H = 1;
PWM_C_L = 1;
PWM_A_H = 0; PWM_A_L = 0;
floatingPhase = ADC_PHASE_U;
break;
case 5:
PWM_A_H = 1;
PWM_C_L = 1;
PWM_B_H = 0; PWM_B_L = 0;
floatingPhase = ADC_PHASE_V;
break;
}
startBlanking();
}

void startBlanking(void)
{
blankTimerTicks = (BLANK_US + TMR0_TICK_US - 1) / TMR0_TICK_US;
adcSampleReady = false;
}

void __interrupt() isr(void)


{
if (INTCONbits.TMR0IF) {
INTCONbits.TMR0IF = 0;
if (blankTimerTicks) {
blankTimerTicks--;
if (blankTimerTicks == 0) {
adcSampleReady = true;
}
}
if (advancePending) {
if (advanceTimerTicks) {
advanceTimerTicks--;
} else {
advancePending = false;
comm_step = (comm_step + 1) % 6;
commutate(comm_step);
}
}
static uint16_t swCounter = 0;
swCounter++;
if (swCounter >= (PWM_PERIOD + 1)) swCounter = 0;
if (swCounter < pwmDuty) {
if ( (comm_step==1) || (comm_step==2) ) {
LATDbits.LATD0 = 1;
} else {
LATDbits.LATD0 = 0;
}
} else {
LATDbits.LATD0 = 0;
}
if (adcSampleReady) {
adcSampleReady = false;
uint16_t val = adc_read(floatingPhase);
const uint16_t mid = 512;
static uint8_t zcount = 0;
if (val > mid)
{
if (zcount < 255) zcount++;
} else {
if (zcount > 0) zcount--;
}
if (zcount >= ZERO_THRESHOLD)
{
gotZeroCross = true;
zcount = 0;
}
}
}
}

1. [Link]

You might also like