📄 example_8_qdec.c
字号:
//-----------------------------------------------------------------------------
// Example 8
// Quadrature Decode
//-----------------------------------------------------------------------------
// Copyright 2004 Silicon Laboratories Inc.
//
// AUTH: KAB
// DATE: 12MAR04
//
// This example provides a quadrature decode interface using the
// external interrupts INT0 and INT1. The external interrupts are
// assigned to P0.0 and P0.1.
//
// The interrupt service routines first complement the appropriate
// interrupt polarity bit and then increment or decrement the global
// variable Position as needed. A nested if...else statement is used
// to determine the appropriate action depending on the status of
// the polarity bits.
//
// The Position variable is output on the UART each time the Position
// changes. The Position can be monitored using a standard Terminal
// application such as Hyperterm. The Terminal should be configured
// for 9600 bps.
//
// Target: C8051F30x
//
// Tool chain: KEIL Eval 'c'
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f300.h> // sfr declarations
#include <stdio.h> // printf()
//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
#define SYSCLK 24500000 // sysclk frequency in Hz
#define BAUDRATE 9600 // baud rate of UART in bps
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
void main (void);
void SYSCLK_Init (void);
void PORT_Init (void);
void UART0_Init (void);
void EINT_Init (void);
void INT0_ISR (void);
void INT1_ISR (void);
//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------
unsigned int Position; // position of quadrature encoder
sbit CHA = P0^0; // quadrature channel A pin state
sbit CHB = P0^1; // quadrature channel B pin state
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main (void)
{
unsigned int p; // last position
PCA0MD = 0x00; // disable watchdog timer
PORT_Init (); // initialize GPIO and Crossbar
SYSCLK_Init (); // initialize System Clock
EINT_Init(); // initialize External Interrupt
UART0_Init (); // initialize UART
Position = 0; // clear initial position
EA = 1; // enable global interrupts
while (1)
{
while(p == Position); // do nothing until moved
p = Position; // update p
printf("%u \r", p); // display position
}
}
//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
void SYSCLK_Init (void)
{
OSCICN = 0x07; // configure for 24.5 MHz
RSTSRC = 0x04; // enable missing clock detector
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports.
// P0.0 - INT0 - CHA input
// P0.1 - INT1 - CHB input
// P0.2 -
// P0.3 -
// P0.4 - UART TX - push-pull output
// P0.5 - UART RX
// P0.6 -
// P0.7 - C2D
//
void PORT_Init (void)
{
XBR0 = 0x03; // skip P0.0 & P0.1
XBR1 = 0x03; // enable uart
P0MDOUT = 0x10; // TX output
XBR2 |= 0x40; // enable crossbars
}
//-----------------------------------------------------------------------------
// EINT_Init
//-----------------------------------------------------------------------------
void EINT_Init (void)
{
IT01CF = 0x10; // INT0=P0.0, INT1=P0.1
if(CHA==0) // check CHA state
IT01CF|=0x08; // if low, trigger high
if(CHB==0) // check CHB state
IT01CF|=0x80; // if low, trigger high
TCON |= 0x05; // set IT0 & IT1 for edge trigger
TCON &= ~0x0a; // clear IE0 and IE1 flags
IP |= 0x05; // INT0 and INT1 high priority
IE |= 0x05; // Enable INT0 and INT1
}
//-----------------------------------------------------------------------------
// INT0_ISR, INT1_ISR
//-----------------------------------------------------------------------------
//
// These two interrupt service routines occur when the respective encoder
// channel changes state. The interrupt service routines are identical
// except for the respective change in the interrupt flag, polarity bit, and
// count direction. The nested if...else statement performs the logical
// equivalent of an exclusive OR function using the polarity bits as the
// quadrature state.
//
void INT0_ISR (void) interrupt 0
{
IT01CF ^= 0x08; // toggle edge select trigger
if ((IT01CF&0x08)==0x08)
if((IT01CF&0x80)==0x80)
Position--; // if both decrement
else
Position++; // if different increment
else
if((IT01CF&0x80)==0x80)
Position++; // if different increment
else
Position--; // if neither decrement
}
void INT1_ISR (void) interrupt 2
{
IT01CF ^= 0x80; // toggle edge select trigger
if ((IT01CF&0x08)==0x08)
if((IT01CF&0x80)==0x80)
Position++; // if both increment
else
Position--; // if different decrement
else
if((IT01CF&0x80)==0x80)
Position--; // if different decrement
else
Position++; // if neither increment
}
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Standard UART0 Init from software examples
//
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON |= 0x10; // T1M = 1; SCA1:0 = xx
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x13; // T1M = 0; SCA1:0 = 01
CKCON |= 0x01;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x13; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x13; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}
TL1 = TH1; // init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit auto-reload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TI0 = 1; // Indicate TX0 ready
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -