Example Source Code:
ME-110 Unicoder Generic C Interface
Description
This example consists of general purpose routines to interface with the unique control interface in the AS5040 sensor chip contained in the Nubotics ME-110. This interface is somewhat similar to SPI. More information can be found on the Austria Microsystems website.
To make this code run on a given microcontroller, you will need to provide your own implementations of delay_us(), set_bit(), clear_bit(), change_bit_to_output(), and change_bit_to_input().
delay_us(int8 microseconds)
delay this number of microseconds set_bit(int pin_number)
assert high the specified digital output pin,
which is wired to the correspondingly named pin on the ME-110 clear_bit(int pin_number)
assert low the specified digital output pin,
which is wired to the correspondingly named pin on the ME-110 change_bit_to_output(int pin_number)
make the specified digital I/O pin a push-pull output rather than an input change_bit_to_input(int pin_number)
make the specified digital I/O pin an input (high impedance)
Download
as5040.c - C source
as5040.h - header file
Source Code
as5040.c
//---------------------------------------------------
// Unicoder C Demo
//
// Copyright 2009, Noetic Design, Inc.
//
// This set of generic C code shows how to access
// the registers of the Unicoder ME-110 encoder.
//---------------------------------------------------
// AS5040 support routines
#include "stdint.h" // or whatever header defines support routines and data types...
BOOL good_checksum;
WORD read_back;
WORD prog_reg;
WORD factory;
// implementation-dependent functions
// to be supplied by user
void delay_us(int8 microseconds)
{
// delay the requested number of microseconds...
// TBD
}
void control_cs(BOOL set, BOOL long_time)
{
if (set)
set_bit(AS_CS); // replace set_bit() with platform-specific method to set an output pin to 1
else
clear_bit(AS_CS); // replace clear_bit() with platform-specific method to clear an output pin to 0
delay_us(long_time ? 6 : 1);
}
void control_clk(BOOL set, BOOL long_time)
{
if (set)
set_bit(AS_CLK);
else
clear_bit(AS_CLK);
delay_us(long_time ? 6 : 1);
}
void control_prog(BOOL set, BOOL long_time)
{
if (set)
set_bit(AS_PROG);
else
clear_bit(AS_PROG);
delay_us(long_time ? 6 : 1);
}
// ******************************
// generic AS5040 access routines
// ******************************
// initialize chip for access
void init_as5040(void)
{
int i;
good_checksum = FALSE;
// set I/O up
change_bit_to_output(AS_CS); // replace with platform-specific routines
change_bit_to_output(AS_CLK);
change_bit_to_output(AS_PROG);
change_bit_to_input(AS_DO);
// shift out factory settings
control_cs(TRUE, FALSE); // AS_CS = 1;
control_clk(FALSE, TRUE); // AS_CLK = 0;
control_prog(TRUE, TRUE); // AS_PROG = 1;
for (i = 0; i < 16; i++)
{
control_clk(TRUE, TRUE); // AS_CLK = 1;
control_clk(FALSE, TRUE); // AS_CLK = 0;
}
control_clk(TRUE, TRUE); // AS_CLK = 1;
control_prog(FALSE, TRUE); // AS_PROG = 0;
control_clk(FALSE, TRUE); // AS_CLK = 0;
control_clk(TRUE, TRUE); // AS_CLK = 1;
get_factory_register(); // read factory settings; must be retained
}
// get the current angle and status BOOLs
int16 get_orientation(void)
{
int i;
int chksum = 0;
int16 orientation = 0;
control_clk(TRUE, FALSE); // AS_CLK = 1; // from smact
control_cs(TRUE, FALSE); // AS_CS = 1;
control_cs(FALSE, FALSE); // AS_CS = 0;
for (i = 0; i < 16; i++)
{
control_clk(FALSE, FALSE); // AS_CLK = 0;
control_clk(TRUE, FALSE); // AS_CLK = 1;
orientation <<= 1;
orientation |= get_bit(AS_DO); // replace get_bit() with platform-specific method to read an input pin
if (i < 13)
chksum ^= get_bit(AS_DO);
}
if (chksum == (orientation & 0x01))
good_checksum = 1;
else
good_checksum = 0;
orientation >>= 1; // remove parity BOOL
delay_us(1);
return orientation;
}
void set_prog_register(WORD value)
{
int i;
WORD mask = 0x8000;
WORD output;
// base line state
control_prog(FALSE, FALSE); // AS_PROG = 0; // from smact
control_clk(TRUE, FALSE); // AS_CLK = 1;
control_cs(TRUE, FALSE); // AS_CS = 1;
control_cs(FALSE, TRUE); // AS_CS = 0; // from smact
control_clk(FALSE, TRUE); // AS_CLK = 0;
control_prog(TRUE, TRUE); // AS_PROG = 1;
control_cs(TRUE, TRUE); // AS_CS = 1;
prog_reg = value;
output = factory;
for (i = 0; i < 32; i++)
{
control_prog(((output & mask) != 0), TRUE); // output most significant BOOL first
if (i == 15)
output = value;
mask >>= 1;
if (!mask)
mask = 0x8000;
control_clk(TRUE, TRUE); // AS_CLK = 1;
control_clk(FALSE, TRUE); // AS_CLK = 0;
}
control_prog(FALSE, TRUE); // AS_PROG = 0;
control_cs(FALSE, TRUE); // AS_CS = 0;
control_cs(TRUE, TRUE); // by observation of demo, pulse cs low, then raise clock and leave high
control_clk(TRUE, TRUE); // AS_CLK = 1;
}
void get_factory_register(void)
{
int i;
WORD mask = 0x8000;
WORD output;
// base line state
control_prog(FALSE, FALSE); // AS_PROG = 0; // from smact
control_clk(TRUE, FALSE); // AS_CLK = 1;
control_cs(TRUE, FALSE); // AS_CS = 1;
control_cs(FALSE, TRUE); // AS_CS = 0; // from smact
control_clk(FALSE, TRUE); // AS_CLK = 0;
control_prog(TRUE, TRUE); // AS_PROG = 1;
control_cs(TRUE, TRUE); // AS_CS = 1;
read_back = 0;
control_cs(FALSE, TRUE); // AS_CS = 0;
control_clk(TRUE, TRUE); // AS_CLK = 1;
control_clk(FALSE, TRUE); // AS_CLK = 0; per app note AN 5040-20
set_bit(AS_CS); // AS_CS = 1;
change_bit_to_input(AS_PROG); // make Prog read only; first BOOL is now available
// replace with platform-specific routine to make a pin an input
delay_us(6);
for (i = 0; i < 32; i++)
{
if (get_bit(AS_PROG))
read_back |= mask;
if (i == 15)
{
factory = read_back;
read_back = 0;
}
mask >>= 1;
if (!mask)
mask = 0x8000;
control_clk(TRUE, TRUE); // AS_CLK = 1;
control_clk(FALSE, TRUE); // AS_CLK = 0;
}
set_bit(AS_CLK); // AS_CLK = 1;
change_bit_to_output(AS_PROG); // make Prog push/pull again; replace with platform-specific routine to make a pin an output
delay_us(6);
control_cs(FALSE, TRUE); // AS_CS = 0;
control_prog(FALSE, TRUE); // AS_PROG = 0;
control_clk(FALSE, TRUE); // AS_CLK = 0;
control_cs(TRUE, TRUE); // by observation of demo, pulse cs low, then raise clock and leave high
control_clk(TRUE, TRUE); // AS_CLK = 1;
}
void enter_alignment_mode(void)
{
control_prog(FALSE, TRUE); // start with this low
control_cs(FALSE, TRUE); // and this low too
control_cs(TRUE, TRUE); // this goes high
control_prog(TRUE, TRUE); // then this
control_cs(FALSE, TRUE); // now this goes low -- now in alignment mode
control_prog(FALSE, TRUE); // and then this can go low
}as5040.h
// AS5040 support routines
#ifndef _AS5040_H_
#define _AS5040_H_
// change to match your micro's connections to these pins on the Unicoder ME-110:
#define AS_CS 0x01
#define AS_CLK 0x02
#define AS_DO 0x04
#define AS_PROG 0x08
#define AS_SDA 0x10
#define AS_SCL 0x20
#define AS_CHA 0x40
#define AS_CHB 0x80
typedef struct _as5040 {
int16 par : 1;
int16 mag_dec : 1;
int16 mag_inc : 1;
int16 lin : 1;
int16 cof : 1;
int16 ocf : 1;
int16 angle : 10;
} AS5040;
typedef struct _as5040_prog {
int16 mode : 2;
int16 div : 2;
int16 index : 1;
int16 z : 10;
int16 ccw : 1;
} AS5040PROG;
#define AP_QUAD_512 0x0001 // 0000 0000 0000 0001
#define AP_QUAD_256 0x0005 // 0000 0000 0000 0101
#define AP_QUAD_128 0x0009 // 0000 0000 0000 1001
#define AP_QUAD_64 0x000D // 0000 0000 0000 1101
#define AP_SNMG_512 0x0002 // 0000 0000 0000 0010
#define AP_SNMG_256 0x0006 // 0000 0000 0000 0110
#define AP_SNMG_128 0x000A // 0000 0000 0000 1010
#define AP_SNMG_64 0x000E // 0000 0000 0000 1110
#define APM_MODE 0x0002
#define APR_MODE 0
#define APM_DIV 0x0002
#define APR_DIV 2
#define APM_INDEX 0x0001
#define APR_INDEX 4
#define APM_Z 0x03ff
#define APR_Z 5
#define APM_CCW 0x0001
#define APR_CCW 15
extern WORD factory;
extern bit good_checksum;
extern void delay(void);
extern void long_delay(void);
extern int16 get_orientation(void);
extern void set_prog_register(WORD value, bit read_fact);
extern void init_as5040(void);
extern void enter_alignment_mode(void);
extern void control_cs(bit set, bit long_time);
extern void control_clk(bit set, bit long_time);
extern void control_prog(bit set, bit long_time);
#endif
© 2004-2011 Noetic Design, Inc. All Rights Reserved. Nubotics and WheelWatcher are trademarks of Noetic Design, Inc.