Motor Controller with C8051F120 microcontroller

Hey Everyone! I’ve got a Pololu Qik 2s9v1 Dual Serial Motor Controller which I’m trying to interface with my C8051F120 microcontroller board.

I’m pretty sure I have all my bit assignments right (not using the reset or error pins at this point). I’m trying to get it to communicate through the UART0 port but its just not happening!

The code we’re using is below. Any help would be greatly appreciated!

//------------------------------------------------------------------------------------
// F12x_Blinky.c
//------------------------------------------------------------------------------------
// Copyright © 2007 Silicon Laboratories, Inc.
//
// AUTH: BD
// DATE: 1 JUL 2002
//
// This program flashes the green LED on the C8051F120 target board about five times
// a second using the interrupt handler for Timer3.
// Target: C8051F12x
//
// Tool chain: KEIL Eval ‘c’
//

//------------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------------
// SFR declarations
#include
//#include
//#include

//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F12x
//-----------------------------------------------------------------------------
sfr16 TMR3RL = 0x92; // Timer3 reload value
sfr16 RCAP3 = 0xCA; // Timer3 reload value
sfr16 TMR3 = 0xCC; // Timer3 counter

//------------------------------------------------------------------------------------
// Global CONSTANTS
//------------------------------------------------------------------------------------

#define SYSCLK 3062500 // approximate SYSCLK frequency in Hz

sbit LED = P1^6; // green LED: ‘1’ = ON; ‘0’ = OFF
sbit left_ir = P1^1;
sbit right_ir = P1^0;
sbit front_ir = P1^3;
char send_byte;
unsigned short new_cmd_send; //-- set each time new
// command is received
//------------------------------------------------------------------------------------
// Function PROTOTYPES
//------------------------------------------------------------------------------------
void Init_Clock(void); //-- initialize the clock to use external
// crystal oscillator
void PORT_Init (void);

void Init_UART0(void); //-- configure and initialize the UART0
// serial comm
void Timer3_Init (unsigned int counts);
void Timer3_ISR (void); //-- ISR for Timer 3
void UART0_ISR(void); //-- ISR for UART0
void MotorForward(unsigned int speed);
void sendByte(unsigned int byteToSend);
// Bytes used to talk to the motor controller

#define INITIALPACKET 0xAA
#define MOTOR0FORWARDPACKET 0x88
#define MOTOR0FORWARDFASTPACKET 0x89
#define MOTOR0REVERSEPACKET 0x8A
#define MOTOR0REVERSEFASTPACKET 0x8B

#define MOTOR1FORWARDPACKET 0x8C
#define MOTOR1FORWARDFASTPACKET 0x8D
#define MOTOR1REVERSEPACKET 0x8E
#define MOTOR1REVERSEFASTPACKET 0x8F

#define MOTOR0COASTPACKET 0x86
#define MOTOR1COASTPACKET 0x87
#define FWVERSIONPACKET 0x81
#define ERRORPACKET 0x82
#define GETCONFIG 0x83
#define SETCONFIG 0x84
//------------------------------------------------------------------------------------
// MAIN Routine
//------------------------------------------------------------------------------------
void main (void) {

// send_byte = 2;
// new_cmd_send = 0;
// EA = 0; //-- disable global interrupts
WDTCN = 0xDE; //-- disable watchdog timer
WDTCN = 0xAD;
Init_Clock();
PORT_Init();
// Timer3_Init(SYSCLK / 12 / 10);
Init_UART0();
// EA = 1; //-- enable global interrupts

while(1) {

// EA = 0;
MotorForward(56);
// Timer3_Init(SYSCLK / 12 / 10);
// EA = 1; //-- enable interrupts

}//}
}

//--------------------------------------------------------------
//--------------------------------------------------------------
void MotorForward(unsigned int speed)
{
if ( speed > 127 )
{
sendByte(MOTOR0FORWARDFASTPACKET);
sendByte(speed-127);
}
else
{
sendByte(MOTOR0FORWARDPACKET);
sendByte(speed);
}
}
//--------------------------------------------------------------
//--------------------------------------------------------------
void sendByte(unsigned int byteToSend)
{
char SFRPAGE_SAVE = SFRPAGE;
SFRPAGE = UART0_PAGE;
//send the packet

SBUF0 = byteToSend;
SFRPAGE = SFRPAGE_SAVE;
}

//--------------------------------------------------------------
//--------------------------------------------------------------

void Init_Clock(void)
{

OSCXCN = 0x67; //-- 0110 0111b
//-- External Osc Freq Control Bits (XFCN2-0) set to 111
//because crystal frequency > 6.7 MHz
//-- Crystal Oscillator Mode (XOSCMD2-0) set to 110

//-- wait till XTLVLD pin is set
while ( !(OSCXCN & 0x80) );
OSCICN = 0x88; //-- 1000 1000b
//-- Bit 2 : Internal Osc. disabled (IOSCEN = 0)
//-- Bit 3 : Uses External Oscillator as System Clock
//(CLKSL = 1)
//-- Bit 7 : Missing Clock Detector Enabled (MSCLKE = 1)
}

//--------------------------------------------------------------
//--------------------------------------------------------------

//------------------------------------------------------------------------------------
// PORT_Init
//------------------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports
//
void PORT_Init (void)
{
XBR2 = 0x40; // Enable crossbar and weak pull-ups
P1MDOUT |= 0x40; // enable P1.6 (LED) as push-pull output
// P1MDIN = 0x40;
XBR0 = 0x04; //-- Enable UART0
XBR1 = 0x00;
// XBR2 = 0x40; //-- Enable Crossbar and weak pull-ups
// (globally)
P0MDOUT |= 0x01; //-- Enable TX0 as a push-pull o/p
// P1MDOUT |= 0x40; //-- Enable P1.6 (LED) as push-
// pull output
}

//--------------------------------------------------------------

//--------------------------------------------------------------

void Init_UART0(void)
{
//-- set up Timer 1 to generate the baude rate (115200)
//for UART0
CKCON |= 0x10; //-- T1M=1; Timer 1 uses the system clock
// 22.11845 MHz
TMOD = 0x20; //-- Timer 1 in Mode 2 (8-bit auto-
// reload)
TH1 = 0xB8; //Baud rate = 9600 //0xF4; //-- Baud rate = 115200
TR1 = 1; //-- start Timer 1 (TCON.6 = 1)
TCON &= 0xCF; //-- Timer 1 overflows used for receive &
// transmit clock (RCLK0=0, TCLK0=0)

//-- Set up the UART0
PCON |= 0x80; //-- SMOD0=1 (UART0 baud rate divide-by-2
// disabled)
SCON0 = 0x50; //-- UART0 Mode 1, Logic level of stop
// bit ignored and Receive enabled

//-- enable UART0 interrupt
IE |= 0x10;
IP |= 0x10; //-- set to high priority level

TI0= 1; //-- clear the receive interrupt flag;
// ready to receive more
}
//--------------------------------------------------------------
//--------------------------------------------------------------

//------------------------------------------------------------------------------------
// Timer3_Init
//------------------------------------------------------------------------------------
//
// Configure Timer3 to auto-reload and generate an interrupt at interval
// specified by using SYSCLK/12 as its time base.
//
//
void Timer3_Init (unsigned int counts)
{
TMR3CN = 0x00; // Stop Timer3; Clear TF3;
// use SYSCLK/12 as timebase
RCAP3 = -counts; // Init reload values
TMR3RL = -counts; //-- Init reload values
TMR3 = 0xffff; // set to reload immediately
EIE2 |= 0x01; //-- enable Timer3 interrupts
// EIE2 |= 0x01; // enable Timer3 interrupts
TMR3CN |= 0x04; //-- start Timer3 by setting TR3
// (TMR3CN.2) to 1 }
TR3 = 1; // start Timer3
}

//------------------------------------------------------------------------------------
// Interrupt Service Routines
//------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------
// Timer3_ISR
//------------------------------------------------------------------------------------
// This routine changes the state of the LED whenever Timer3 overflows.
//
// NOTE: The SFRPAGE register will automatically be switched to the Timer 3 Page
// When an interrupt occurs. SFRPAGE will return to its previous setting on exit
// from this routine.
//
void Timer3_ISR (void) interrupt 14
{
TMR3CN &= ~(0x80); //-- clear TF3

TF3 = 0; // clear TF3

LED = ~LED; // change state of LED

}

//--------------------------------------------------------------
//--------------------------------------------------------------
void UART0_ISR(void) interrupt 4
{
//-- pending flags RI0 (SCON0.0) and TI0(SCON0.1)
if ( TI0 == 1) //-- interrupt caused by sent byte
{
send_byte = SBUF0; //-- read the input buffer
TI0 = 0; //-- clear the flag
new_cmd_send=1;
}
}

//--------------------------------------------------------------
//--------------------------------------------------------------

Hello.

I’m not familiar with your microcontroller, so I can’t really give you any specific help, and your program is way too long for me to look over in any qualitative way. If you want some help, please post the simplest program that should do something but doesn’t (you can probably send a serial command in under twenty lines), and please use the Code button to bracket it in [ code ][ /code ] tags and make it more readable. Also, does your qik work as expected if you put it in demo mode?

The qik responds to TTL serial commands, so basically you just need to figure out how to send TTL serial bytes with your microcontroller. If you have a USB-to-serial adapter, you can try sending bytes through it to your computer and monitoring them with a terminal program to see if your transmissions are getting through as you expect, and you can use the Pololu Serial Transmitter utility to send commands from your computer to the qik to make sure the problem really is with your microcontroller code. Once you have that working, communicating with the qik should just be a matter of changing the byte values you’re sending.

- Ben