amith.srivatsa
Junior Member level 1
Dear all,
I just changed from PIC16f690 to PIC16F876A. The PIC is used for motor driver application and it sends signals to the H-bridge VNH2SP30. The code written for PIC16f690 worked well with no errors.
But now, I am getting some errors, mainly unknown keyword, unknown identifier when I try to compile the same code but this time for PIC16F876A. I just have changed the header files. Can anyone help me in debugging these errors ?
The code is below:
/*
Compile with CCS, see https://ccsinfo.com/ for details.
Sample - To test: Send via i2c to address 0x50 this data--> 0x02107F in order to set the motors to "Forward" & Half speed.
Setup: pin A5: serial communication
pin C0,C1: INA and INB for Motor1 (left)
pin C6,C7: INA and INB for Motor2 (right)
pin C2,C3: PWM for motor 1 & 2 respectively (speed control)
pinB4,B6: I2C communication, SDA & SCL
History:
Version 2:
-Automatic Stop after 600 ms function to stop motors when no i2c command has been send
still problems with prescale and div value but is working
Version 1: August 25th, 2009
- To control speed and direction of two DC motors using two Full H-Bridge VNH2SP30 and a PIC
*/
#include <16F876A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT //Reset when brownout detected
#FUSES MCLR //Master Clear pin enabled
#FUSES NOCPD //No EE protection
#FUSES NOPUT //No Power Up Timer
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#use delay(clock=8000000)
#use rs232(baud=19200, xmit=PIN_A5 ) // used for the serial com
#use i2c(Slave, sda=PIN_B4, scl=PIN_B6 )// used for i2c
/*
Pin defines
*/
#define led PIN_A4
#define driver_a PIN_C0 //INA and INB for motor1
#define driver_b PIN_C1
#define driver_c PIN_C6 //INA and INB for motor2
#define driver_d PIN_C7
#define TYPE 0x01
#define VERSION "V1.4"
#define VERSION_MAJOR 1
#define VERSION_MINOR 4
#define GET_TYPE 0x00
#define GET_VERSION 0x01
#define SET_MOTOR 0x02
/*
Variables
*/
int8 address;
int8 state;
int1 dataready = false;
int1 counting = false;
long int timerone = 0;
int overflow = 0;
int8 mode = 0;
int8 databyte1 = 0;
int8 databyte2 = 0;
/*
Function prototypes
*/
// description: This funtion enables or disables INA,INB imputs for both VNH2SP30 Full-bridges.
// arguments: Boolean enable
// return: None
void EnableDrivers( int1 enable );
// description: This funtion sets pwm according to the speed and INA, INB according to command for both motors
// arguments: int8 config
// int8 duty
// return: None
void SetDCControl( int8 config, int8 duty );
// There are some issues with the PWM module, before changing pinout please clear.
void clear( void );
// describtion: this function reads the address
// arguments: none
// return : the full adress ( 8bit wise)
int8 ReadAddress ( void );
// describtion: this function is used to process received data from the I2C bus.
// arguments: recieved byte 1 and received byte 2
// return : none
void ProcessData( int8 byte1, int8 byte2 );
// Interrupt service routine for i2c activty
#int_SSP
void SSP_isr(){
output_high(led);
// you will only be interrupted if the address is correct.
// first check the mode: read or write
state = i2c_isr_state();
if(state < 0x80){ //Master is sending data
if(state == 0){}
else if(state == 1)
{
mode = i2c_read();
}
else if(state == 2)
{
databyte1 = i2c_read();
}
else if(state == 3)
{
databyte2 = i2c_read();
if( mode == SET_MOTOR)
{
dataready = true;
}
}
}
else if( state == 0x80 ) // master is reading data
{
if( mode == GET_TYPE )
{
i2c_write( TYPE );
}
else if( mode == GET_VERSION)
{
i2c_write( VERSION_MAJOR );
}
}
else if( state == 0x81 ) // master is reading data
{
i2c_write( VERSION_MINOR );
}
output_low(led);
return;
}
////////////////////////////////////////////////////////////////////////////
void main(){
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
//setup_timer_1(T1_DISABLED);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);//timer1 for automatic stop after 600ms function
setup_timer_2(T2_DIV_BY_16, 124, 1); // 1000 Hz, the pwm frequency
setup_comparator(NC_NC_NC_NC);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
setup_oscillator(OSC_8MHZ);
printf("I2C motor driver with I2C\n\r");//print to serial
printf("Version %s\n\r", VERSION);
EnableDrivers( false );//True --> INA and INB automatically enabled at startup, False-->Vice-versa
address = ReadAddress();
printf("The address = '%X'\n\r", address);
I2C_SlaveAddr( address );
clear();
while(1){
if( dataready == true ){
printf("Command = '%02x' '%02X'\n\r", databyte1, databyte2);
ProcessData( databyte1, databyte2 );
set_timer1(0);
overflow = 0;
counting = true;
dataready = false;
}
if((counting == true)){
timerone = (get_timer1()/625);
if(timerone>=97){
overflow += 1;
}
if(( overflow >= 5) ) {
EnableDrivers(False);
printf("Its friday & the rover has stopped !\n\r");
overflow = 0;
counting= false;
}
}
delay_ms(10);
}
}
/////////////////////////////////////////////////////////////////////////////
/*
Funtion boddies
*/
void EnableDrivers( values ){
if( values ){
output_high( driver_a );
output_high( driver_b );
output_high( driver_c );
output_high( driver_d );
}
else{
output_low( driver_a );
output_low( driver_b );
output_low( driver_c );
output_low( driver_d );
}
}
void SetDCControl( int8 config, unsigned int duty ){
int secs = 3;
int i;
duty >>= 1;
set_pwm1_duty( duty );
printf("Duty %u\n\r", duty);
switch( config )
{
case 0:
printf("Forward\n\r");
clear();
setup_ccp1(CCP_PWM | CCP_PWM_H_H | CCP_PULSE_STEERING_D | CCP_PULSE_STEERING_C ); // forward correspond to pin RC2 and RC3
output_high(driver_a);
output_low(driver_b);
output_high(driver_c);
output_low(driver_d);
break;
case 1:
for(i=0;i<secs;i++)
{
printf("Turn left\n\r");
clear();
setup_ccp1(CCP_PWM | CCP_PWM_H_H | CCP_PULSE_STEERING_D | CCP_PULSE_STEERING_C ); // turn left
output_high(driver_a);
output_low(driver_b);
output_low(driver_c);
output_high(driver_d);
}
dataready = false;
break;
case 2:
printf("Turn right\n\r");
clear();
setup_ccp1(CCP_PWM | CCP_PWM_H_H | CCP_PULSE_STEERING_D | CCP_PULSE_STEERING_C ); // turn rightt
output_low(driver_a);
output_high(driver_b);
output_high(driver_c);
output_low(driver_d);
break;
case 3:
printf("Backward\n\r");
clear();
setup_ccp1(CCP_PWM | CCP_PWM_H_H | CCP_PULSE_STEERING_D | CCP_PULSE_STEERING_C ); // backward
output_low(driver_a);
output_high(driver_b);
output_low(driver_c);
output_high(driver_d);
break;
default:
printf("Invalid Argument!\n\r");
clear();
setup_ccp1(CCP_PWM | CCP_PWM_H_H );
output_low( PIN_C2);
output_low( PIN_C3);
output_low( PIN_C4);
output_low( PIN_C5);
break;
}
}
void clear( void ){
setup_ccp1(CCP_PWM | CCP_PWM_H_H | CCP_PULSE_STEERING_A | CCP_PULSE_STEERING_B | CCP_PULSE_STEERING_C | CCP_PULSE_STEERING_D );
output_low( PIN_C2);
output_low( PIN_C3);
output_low( PIN_C4);
output_low( PIN_C5);
}
int8 ReadAddress(){
int8 temp = 0xA0;// the base address is 1010000 (i2c address has only 7 bits!!), corresponds to address 0x50
return temp;
}
void ProcessData( int8 Data1, int8 Data2)
{
int8 Mode;
int8 Directions;
// determine wich mode is used
Mode = Data1;
Mode >>= 4;
switch( Mode )
{
case 1:
printf( "mode1\n\r" );
Directions = Data1 & 0x03; // only the two LSB are needed
SetDCControl( Directions, Data2);
break;
default:
printf( "mode unknown\n\r" );
break;
}
return;
}
I just changed from PIC16f690 to PIC16F876A. The PIC is used for motor driver application and it sends signals to the H-bridge VNH2SP30. The code written for PIC16f690 worked well with no errors.
But now, I am getting some errors, mainly unknown keyword, unknown identifier when I try to compile the same code but this time for PIC16F876A. I just have changed the header files. Can anyone help me in debugging these errors ?
The code is below:
/*
Compile with CCS, see https://ccsinfo.com/ for details.
Sample - To test: Send via i2c to address 0x50 this data--> 0x02107F in order to set the motors to "Forward" & Half speed.
Setup: pin A5: serial communication
pin C0,C1: INA and INB for Motor1 (left)
pin C6,C7: INA and INB for Motor2 (right)
pin C2,C3: PWM for motor 1 & 2 respectively (speed control)
pinB4,B6: I2C communication, SDA & SCL
History:
Version 2:
-Automatic Stop after 600 ms function to stop motors when no i2c command has been send
still problems with prescale and div value but is working
Version 1: August 25th, 2009
- To control speed and direction of two DC motors using two Full H-Bridge VNH2SP30 and a PIC
*/
#include <16F876A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT //Reset when brownout detected
#FUSES MCLR //Master Clear pin enabled
#FUSES NOCPD //No EE protection
#FUSES NOPUT //No Power Up Timer
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#use delay(clock=8000000)
#use rs232(baud=19200, xmit=PIN_A5 ) // used for the serial com
#use i2c(Slave, sda=PIN_B4, scl=PIN_B6 )// used for i2c
/*
Pin defines
*/
#define led PIN_A4
#define driver_a PIN_C0 //INA and INB for motor1
#define driver_b PIN_C1
#define driver_c PIN_C6 //INA and INB for motor2
#define driver_d PIN_C7
#define TYPE 0x01
#define VERSION "V1.4"
#define VERSION_MAJOR 1
#define VERSION_MINOR 4
#define GET_TYPE 0x00
#define GET_VERSION 0x01
#define SET_MOTOR 0x02
/*
Variables
*/
int8 address;
int8 state;
int1 dataready = false;
int1 counting = false;
long int timerone = 0;
int overflow = 0;
int8 mode = 0;
int8 databyte1 = 0;
int8 databyte2 = 0;
/*
Function prototypes
*/
// description: This funtion enables or disables INA,INB imputs for both VNH2SP30 Full-bridges.
// arguments: Boolean enable
// return: None
void EnableDrivers( int1 enable );
// description: This funtion sets pwm according to the speed and INA, INB according to command for both motors
// arguments: int8 config
// int8 duty
// return: None
void SetDCControl( int8 config, int8 duty );
// There are some issues with the PWM module, before changing pinout please clear.
void clear( void );
// describtion: this function reads the address
// arguments: none
// return : the full adress ( 8bit wise)
int8 ReadAddress ( void );
// describtion: this function is used to process received data from the I2C bus.
// arguments: recieved byte 1 and received byte 2
// return : none
void ProcessData( int8 byte1, int8 byte2 );
// Interrupt service routine for i2c activty
#int_SSP
void SSP_isr(){
output_high(led);
// you will only be interrupted if the address is correct.
// first check the mode: read or write
state = i2c_isr_state();
if(state < 0x80){ //Master is sending data
if(state == 0){}
else if(state == 1)
{
mode = i2c_read();
}
else if(state == 2)
{
databyte1 = i2c_read();
}
else if(state == 3)
{
databyte2 = i2c_read();
if( mode == SET_MOTOR)
{
dataready = true;
}
}
}
else if( state == 0x80 ) // master is reading data
{
if( mode == GET_TYPE )
{
i2c_write( TYPE );
}
else if( mode == GET_VERSION)
{
i2c_write( VERSION_MAJOR );
}
}
else if( state == 0x81 ) // master is reading data
{
i2c_write( VERSION_MINOR );
}
output_low(led);
return;
}
////////////////////////////////////////////////////////////////////////////
void main(){
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
//setup_timer_1(T1_DISABLED);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);//timer1 for automatic stop after 600ms function
setup_timer_2(T2_DIV_BY_16, 124, 1); // 1000 Hz, the pwm frequency
setup_comparator(NC_NC_NC_NC);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
setup_oscillator(OSC_8MHZ);
printf("I2C motor driver with I2C\n\r");//print to serial
printf("Version %s\n\r", VERSION);
EnableDrivers( false );//True --> INA and INB automatically enabled at startup, False-->Vice-versa
address = ReadAddress();
printf("The address = '%X'\n\r", address);
I2C_SlaveAddr( address );
clear();
while(1){
if( dataready == true ){
printf("Command = '%02x' '%02X'\n\r", databyte1, databyte2);
ProcessData( databyte1, databyte2 );
set_timer1(0);
overflow = 0;
counting = true;
dataready = false;
}
if((counting == true)){
timerone = (get_timer1()/625);
if(timerone>=97){
overflow += 1;
}
if(( overflow >= 5) ) {
EnableDrivers(False);
printf("Its friday & the rover has stopped !\n\r");
overflow = 0;
counting= false;
}
}
delay_ms(10);
}
}
/////////////////////////////////////////////////////////////////////////////
/*
Funtion boddies
*/
void EnableDrivers( values ){
if( values ){
output_high( driver_a );
output_high( driver_b );
output_high( driver_c );
output_high( driver_d );
}
else{
output_low( driver_a );
output_low( driver_b );
output_low( driver_c );
output_low( driver_d );
}
}
void SetDCControl( int8 config, unsigned int duty ){
int secs = 3;
int i;
duty >>= 1;
set_pwm1_duty( duty );
printf("Duty %u\n\r", duty);
switch( config )
{
case 0:
printf("Forward\n\r");
clear();
setup_ccp1(CCP_PWM | CCP_PWM_H_H | CCP_PULSE_STEERING_D | CCP_PULSE_STEERING_C ); // forward correspond to pin RC2 and RC3
output_high(driver_a);
output_low(driver_b);
output_high(driver_c);
output_low(driver_d);
break;
case 1:
for(i=0;i<secs;i++)
{
printf("Turn left\n\r");
clear();
setup_ccp1(CCP_PWM | CCP_PWM_H_H | CCP_PULSE_STEERING_D | CCP_PULSE_STEERING_C ); // turn left
output_high(driver_a);
output_low(driver_b);
output_low(driver_c);
output_high(driver_d);
}
dataready = false;
break;
case 2:
printf("Turn right\n\r");
clear();
setup_ccp1(CCP_PWM | CCP_PWM_H_H | CCP_PULSE_STEERING_D | CCP_PULSE_STEERING_C ); // turn rightt
output_low(driver_a);
output_high(driver_b);
output_high(driver_c);
output_low(driver_d);
break;
case 3:
printf("Backward\n\r");
clear();
setup_ccp1(CCP_PWM | CCP_PWM_H_H | CCP_PULSE_STEERING_D | CCP_PULSE_STEERING_C ); // backward
output_low(driver_a);
output_high(driver_b);
output_low(driver_c);
output_high(driver_d);
break;
default:
printf("Invalid Argument!\n\r");
clear();
setup_ccp1(CCP_PWM | CCP_PWM_H_H );
output_low( PIN_C2);
output_low( PIN_C3);
output_low( PIN_C4);
output_low( PIN_C5);
break;
}
}
void clear( void ){
setup_ccp1(CCP_PWM | CCP_PWM_H_H | CCP_PULSE_STEERING_A | CCP_PULSE_STEERING_B | CCP_PULSE_STEERING_C | CCP_PULSE_STEERING_D );
output_low( PIN_C2);
output_low( PIN_C3);
output_low( PIN_C4);
output_low( PIN_C5);
}
int8 ReadAddress(){
int8 temp = 0xA0;// the base address is 1010000 (i2c address has only 7 bits!!), corresponds to address 0x50
return temp;
}
void ProcessData( int8 Data1, int8 Data2)
{
int8 Mode;
int8 Directions;
// determine wich mode is used
Mode = Data1;
Mode >>= 4;
switch( Mode )
{
case 1:
printf( "mode1\n\r" );
Directions = Data1 & 0x03; // only the two LSB are needed
SetDCControl( Directions, Data2);
break;
default:
printf( "mode unknown\n\r" );
break;
}
return;
}