波特率:9600
#include <hidef.h> /* for EnableInterrupts macro */
#include <MC68HC908RK2.h> /* include peripheral declarations */
/*****************************************************************************/
/* PROJECT : RF key demonstrator (ASK or FSK) */
/* constant file */
/*****************************************************************************/
/* Protocol */
#define nb_wake_up_bit 0 // not using the variable to delay for some time.
#define Preamble 0xFB86 // End of Tone + ID (B8) + Header (for using Romeo2 SPI)
#define Device_ID 0x7800 // length = 4 ; from $7800 to $7803
// NOTE: <IMPORTANT> Each of these 4 bytes must be programmed
// individually for each RK/RF2 upon programming the flash,
// and represent the tire identification.
#define wait_0_2ms 400 // for temperature sense
#define wait_0_5ms 1000 // for L22B pressure sense
#define wait_0_8ms 1600 // for long L90J pressure sense
#define wait_1ms 2000 // = 1 ms
#define wait_1_8ms 3810 // = 1.8 ms for Tango3
#define wait_2ms 4000 // = 2 ms for Remeo2
/* Transmission Timer Clock Generator */
/* This is the section that must be modified when the crystal is changed. */
/* You will also have to clear TSC[2:0] during transmission (see emis1.asm) */
/* ~9600 bauds using MCU clock for timer (not as accurate over temperature) */
// #define UHF_period 200 // =2MHz/10000bauds
// #define UHF_Duty_Cycle 100 // =0.5*UHF_period
/* use of DATACLK at 9600 bauds, 434 MHz*/
#define UHF_Period 22 // = 212kHz/9600 bauds
#define UHF_Duty_Cycle 11 // = 50%
/* use of DATACLK at 4800 bauds, 434 MHz*/
//#define UHF_period 44 // = 212kHz/4800 bauds
//#define UHF_Duty_Cycle 22 // = 50%
/* use of DATACLK at 9600 bauds, 315 MHz*/
// #define UHF_period 16 // = 154kHz/9600 bauds
// #define UHF_Duty_Cycle 8 // = 50%
/* use of DATACLK at 1200 bauds, 434 MHz:*/
// #define UHF_period_park 176 // = 212kHz/1200 bauds
// #define UHF_Duty_Cycle_park 88 // = 50%
/* use of DATACLK at 1200 bauds, 315 MHz:*/
// #define UHF_period_park 128 // = 154kHz/1200 bauds
// #define UHF_Duty_Cycle_park 64 // = 50%
//** hardef.h
//** Tango 3 I/O assignments
//#define tango_Band PTB_PTB0
#define tango_Band PTA_PTA7
#define tango_Enable PTB_PTB1
#define tango_DATA_RF PTB_PTB2
#define tango_UP_CLOCK PTB_PTB3
//#define tango_Mode PTA_PTA7 // PA7 **Important: porta!!! NOT portb!!!
#define tango_Mode PTB_PTB0
//* Mode Control pins *
//#define S1 PTA_PTA1
//#define S0 PTA_PTA2
#define S1 PTA_PTA2
#define S0 PTA_PTA3
//* Digital Data Output Pin *
//#define DOUT_BAR PTA_PTA3
//#define DOUTb PTA_PTA3
#define DOUT_BAR PTA_PTA1
#define DOUTb PTA_PTA1
//* Data Clock Pin *
#define DCLK PTA_PTA4
//* Serial Data In Pin *
#define SDATA PTA_PTA5
#define DDATA PTA_PTA5
#define LOWV 0x20
#define LVIOUT 0x80
#define nb_tx_byte 10
/*****************************************************************************/
/* PROJECT : RF key demonstrator (ASK or FSK) */
/* Variable file */
/* Modified by Jeff Burgess */
/* - added work-around for bug in Romeo2 receiver, where its SPI corrupts */
/* the last bit of data in the frame. Simply transmit one more useless */
/* byte, that will be corrupted instead of the useful data. */
/*****************************************************************************/
//*** define tyre's ID @ 0x7800
//const uchar ID[]@Device_ID = {0x55,0x10,0x77,0x77};
const uchar ID[]@Device_ID = {0x55,0x10,0x02,0x01};
//const uchar ID[]@Device_ID = {0x55,0x10,0x02,0x02};
//const uchar ID[]@Device_ID = {0x55,0x10,0x02,0x03};
//const uchar ID[]@Device_ID = {0x55,0x10,0x02,0x04};
//const uchar ID[]@Device_ID = {0x55,0x10,0x02,0x05};
//const uchar ID[]@Device_ID = {0x55,0x10,0x02,0x06};
//const uchar ID[]@Device_ID = {0x55,0x10,0x02,0x07};
//const uchar ID[]@Device_ID = {0x55,0x10,0x02,0x08};
//const uchar ID[]@Device_ID = {0x55,0x10,0x02,0x09};
// transmit variables
// Preamble (2 bytes) - Device ID (4 bytes) - daytona data (2 bytes) -
// Status (1 byte) - CRC (1 byte) - Junk (1 byte)
uchar Tx_Byte[nb_tx_byte];
uchar Current_Tx_Bit;
uchar Next_Tx_Bit;
uchar current_tx_byte;
/* hardware variables for Daytona */
// variables for Daytona Serial and SAR routines
uchar T2; // temporary variables
uchar T3; //
uchar T4; //
uchar T5; //
uchar SAR; //
uchar STATUS; //
uchar Tx_count; // Measure pressure every 3 sec, tx every 54 sec.
uchar Max_Pres; // Holds the maximum pressure
uchar Min_Pres; // Holds the minimum pressure
uchar AVGCOUNT; // Averaging counter (only used with noisy L22B silicon)
uchar TEMPERATURE; // converted temperature
uchar PRESSURE; // converted pressure
uchar COUNTER; // counter to count every 3 or 6 secs
uchar Random_Number; // Pseudo-random number (from timer counter low register)
void init_ports(void);
void init_icg(void);
void init_timer(void);
void init_kbi(void);
void init_sys(void);
void tango_read_temperature_mode(void);
void tango_read_pressure_mode(void);
void tango_read_data_out(void);
void tango_idle(void);
void asleep_tx(void);
void Daytona_NoTx_Read(void);
void Daytona_Tx_Read(void); // Read temperature and pressure data.
void Check_battery(void);
void Fast_Data_Mode(void);
void Normal_Data_Mode(void);
void Transmit_Prepare(void);
void Transmit_Frame(void); // Process and transmit the data.
void Transmit_Message(void);
void Random_delay(void); // Add a random delay (~0 - 100 ms).
void tempo(uint ch);
void delay_200_ms(void);
void delay_800_ms(void); // Wait for about 0.8 seconds.
void make_frame(void);
uchar ad_converted(void);
void send_byte(uchar ch);
void toggle_clk(void);
/*********************************************************/
/* 函数:interrupt void Tx_UHF_ISR(void); */
/* 功能:中断程序,将数据按曼彻斯特码发射出去 */
/*********************************************************/
/* Tx_UHF_ISR */
/* Description : it decides what to do on timer overflow */
/* if current = next, then toggle on timer overflow,*/
/* else no toggle */
/* In : Next_Tx_bit, Current_Tx_Bit */
/* Out : TSC0, nb_1 */
/* local variables : */
/*********************************************************/
interrupt void Tx_UHF_ISR(void){
asm LDA TSC0 // reenable next input capture isr by reading tsc0
TSC0_CH0F = 0; // clearing input capture flag
if(!(Next_Tx_Bit==Current_Tx_Bit)){
TSC0_TOV0 = 0; //No Tovf
}
else{
TSC0_TOV0 = 1; // Tovf
}
}
/*********************************************************/
/* 函数:__interrupt void Cpu_Interrupt(void) */
/* 功能:中断程序,执行空操作 */
/*********************************************************/
interrupt void KB_entry(void){
tango_Enable = 1; // replace the contents in <emis1.asm>
INTKBSCR_IMASKK = 1; // Disable keyboard Interrupts.
Daytona_NoTx_Read(); // Read pressure data (not include temperature)
Tx_count++;
if(Tx_count==1){
Transmit_Prepare();
}
init_kbi();
init_ports();
tango_idle();
asm stop
}
/*********************************************************/
/* 函数:void main(void); */
/*********************************************************/
void main(void) {
DisableInterrupts; /* disable interrupts */
/* include your code here */
//CONFIG = 0x32; // LVISTOP disabled!!!
// CONFIG[0]=COPD=0:ENABLE WATCHDOG!
// timeout period = 2**18-2**4 CGMXCLK cycles
CONFIG = 0x33; // WATCHDOG disabled!!!
init_sys(); // Initialize Module, clear counters/variables.
tango_idle(); // Place Daytona in IDLE mode and
// asm stop // wait here for falling edge at DOUT.
// when using sensor.
//*** for test program
for(;;) {
PTA_PTA6 = ~PTA_PTA6; //FOR TEST ok!
Transmit_Frame();
} // loop forever /
//please make sure that you never leave this function /
}
/**************************************************************/
/* LVI status check routine */
/* V0.1 17 July, 2002 Jeff Burgess */
/* Called with: jsr SEND_BYTE */
/* Returns: STATUS[7,6] containing the data */
/* from LVISR[7,5] respectively. */
/* (c) 2002 Motorola */
/**************************************************************/
void Check_battery(void){
asm LDA LVISR
T3 = LVISR;
if(0!=(T3&LOWV)){ //LOWV is bit 5 0010-0000
//STATUS.S_LOWV = 1;
}
if(0!=(T3&LVIOUT)){
//STATUS.S_LVIOUT = 1; //LVIOUT is bit 7 1000-0000
}
}
/**************************************************************/
/* 函数:void Daytona_NoTx_Read(void); */
/* 功能:没到发射时间只采样压力值 */
/* 须更新最大最小压力值:Max_Pres 和 Min_Pres */
/**************************************************************/
void Daytona_NoTx_Read(void){
tango_read_pressure_mode(); //Sample pressure
tempo(wait_0_5ms);
tango_read_data_out();
PRESSURE = ad_converted();
tango_idle();
if(PRESSURE>Max_Pres){
Max_Pres = PRESSURE;
}
else if(PRESSURE<Min_Pres){
Min_Pres = PRESSURE;
}
else {
}
}
/**************************************************************/
/* 函数:void Daytona_Tx_Read(void); */
/* 功能:已到发射时间,采样压力和温度值 */
/**************************************************************/
void Daytona_Tx_Read(void){
tango_read_temperature_mode();
tempo(wait_0_2ms);
tango_read_data_out();
TEMPERATURE = ad_converted();
tango_read_pressure_mode();
tempo(wait_0_5ms);
PRESSURE = ad_converted();
tango_idle();
}
/**************************************************************/
/* 函数:uchar ad_converted(void); */
/* 功能:A/D转换程序,用以采集MPXY8020传感器的温度、压力数据 */
/**************************************************************/
uchar ad_converted(void){
uchar i;
uchar data=0;
uchar ad_data;
uchar data_buff;
SAR = 0;
T2 = 0x80;
for(i=1;i<8;i++){
data_buff = T2|SAR;
send_byte(data_buff);
if(1==DOUT_BAR) { //TOO LOW
SAR |=T2;
}
else{
T2 = T2>>1;
}
}
ad_data = SAR;
return ad_data;
}
void send_byte(uchar ch){
uchar data;
uchar mask = 0x80;
uchar i; //bit count
data = ch;
DCLK = 0;
for(i=8;i>0;i--){
if(1==data&mask){
SDATA = 1;
toggle_clk();
}
else{
SDATA = 0;
toggle_clk();
}
}
}
void toggle_clk(void){
DCLK = 1;
DCLK = 0;
}
/*********************************************************/
/* 函数:void Transmit_Prepare(void) */
/* 功能: */
/*********************************************************/
void Transmit_Prepare(void){
uchar i;
uchar fast_mode_flag = 0;
Check_battery();
if(5==(Max_Pres-Min_Pres)) {
Fast_Data_Mode();
}
else{
Normal_Data_Mode();
}
i = Tx_count;
for(i;i>0;i--){
Daytona_Tx_Read(); // Read temperature and pressure data.
Transmit_Frame();
Random_delay(); // Add a random delay (~0 - 100 ms).
}
}
/**************************************************************/
/* Transmit_Frame */
/* Description : Make the data frame and transmit it out. */
/* In : */
/* Out : */
/* local variables : */
/**************************************************************/
void Transmit_Frame(void){
make_frame();
tango_Enable = 1;
tempo(wait_1_8ms); // wake up Romeo2 (mc33594)
tempo(wait_1_8ms); // wake up Romeo2 (mc33594)
/* Description : it transmits a tone at 9600 bauds for the programmed time */
asm lda TSC0
TSC0 &= 0xE3; // initial output = H
// #%11100011
// \\\_______;Pin under port control,
// \________;Initial output = High
// MS0B|MS0A|ELS0B|ELS0A = X000 means initial output==high level.
// initialize timer0
Current_Tx_Bit = 1;
Next_Tx_Bit = 1;
asm lda TSC
TSC = 0x37;
asm lda TSC0
TSC0 =0x54;
// TSC = 0x30;
TMOD = UHF_Period; //for 9600 Baud
TCH0 = UHF_Duty_Cycle;
TSC_TSTOP = 0; // start the timer.bit5
Transmit_Message(); // transmit the UHF frame
}
/**************************************************************/
/* PROJECT : RF key demonstrator (ASK or FSK) */
/* Functions: */
/* Make_frame */
/* Read_ID */
/* Make_daytona_data */
/* Calculate_checksum */
/**************************************************************/
void make_frame(void){
uchar i,check_sum = 0;
Tx_Byte[0] = 0xFB; // Preamble+ID+Header
Tx_Byte[1] = 0x86;
Tx_Byte[2] = ID[0];
Tx_Byte[3] = ID[1];
Tx_Byte[4] = ID[2];
Tx_Byte[5] = ID[3];
// Tx_Byte[6] = PRESSURE;
// Tx_Byte[7] = TEMPERATURE;
// Tx_Byte[8] = STATUS;
// for no sensor transmit test. status byte is incerment by 1 each time.
// Tx_Byte[2] = 0x01; //ID[0]
// Tx_Byte[3] = 0x23; //ID[1]
// Tx_Byte[4] = 0x45; //ID[2]
// Tx_Byte[5] = 0x67; //ID[3]
Tx_Byte[6] = 0x44; //PRESSURE
Tx_Byte[7] = 0x55; //TEMPERATURE
Tx_Byte[8] = 0x66; //STATUS
// calculate from ID[0] to STATUS.
for(i=0;i<7;i++){
check_sum += Tx_Byte[i+2];
}
Tx_Byte[9] = ~check_sum;//CHECKSUM
}
/*****************************************************************************/
/* Transmit */
/* Description : it transmits data at 9600 bauds in Manchester */
/* In : Tx_byte */
/* Out : */
/* local variables : H:X, current_tx_bit,next_tx_bit,current_tx_byte */
/*****************************************************************************/
void Transmit_Message(void){
uchar i,j;// i==byte_counter,j==bit_counter;
uchar mask=0x80;
//include FB86+ID[0]~ID[3]+PRESSURE+TEMPERATURE+STATUS+CHECKSUM
for(i=0;i<10;i++){
current_tx_byte = Tx_Byte[i];
for(j=8;j>0;j--){
Current_Tx_Bit = Next_Tx_Bit;
if(current_tx_byte&mask) { //here error before :2006.01.05
Next_Tx_Bit = 1;
}
else {
Next_Tx_Bit = 0;
}
current_tx_byte <<=1;
asm wait
}
}
asm LDA TSC
TSC_TOF = 0;
while(!TSC_TOF);
tango_DATA_RF = 0;
TSC0 = 0;
tango_DATA_RF = 0;
tempo(UHF_Period);
tempo(UHF_Period);
tempo(UHF_Period);
tango_Band = 1; // shut down the RF, keep at 315/434MHz
asm LDA TSC
TSC = 0x30;
}
void Normal_Data_Mode(void){
Tx_count = 1;
}
void Fast_Data_Mode(void){
Tx_count = 1;
}
void Random_delay(){
asm LDA TCNTL
Random_Number = TCNTL &0x07;
if(Random_Number){
switch(Random_Number){
case 2:{
tempo(49151); //25ms
}break;
case 4:{
tempo(65535); //50ms
tempo(32767);
}break;
case 5:{
tempo(65535); //75ms
tempo(65535);
tempo(16383);
}break;
default:{
tempo(65535); //100ms
tempo(65535);
tempo(65535);
}
}
}
}
// This is a constant delay for approximately 0.8 seconds, used while in
// fast transmission mode.
void delay_200_ms(void){
uchar i;
uint ch;
for(i=6;i>0;i--){
ch = 0xFFFF;
tempo(ch);
}
}
void delay_800_ms(void){
uchar i;
uint ch;
for(i=24;i>0;i--){
ch = 0xFFFF;
tempo(ch);
}
}
/*****************************************************************************/
/* tempo */
/* Description : it waits for n cpu cycles */
/* In : H:X */
/* Out : TMOD, TSC */
/* local variables : */
/*****************************************************************************/
void tempo(uint ch){
asm LDA TSC
TSC_TOF = 0;
TSC |= 0x30; // stop the counter,
TMOD = ch;
TSC_TSTOP = 0; // start the timer
while(!TSC_TOF);
}
/**************************************************************/
/* Init */
/* Description : it initializes the MCU */
/* In : */
/* Out : TEMPERATURE, PRESSURE */
/* local variables : */
/**************************************************************/
void init_sys(void){
init_ports();
init_icg();
init_timer();
Tx_count = 0;
Max_Pres = 0;
Min_Pres = 0xFF;
TEMPERATURE = 0x80;
PRESSURE =0x80; // These initialize the values to 1/2 FS
// for the moving average. This way, the readings will
// probably converge to the mean quicker than with whatever
// random value these variables start at.
init_kbi();
}
/**************************************************************/
/* Init_KBI */
/* Description : it enables keyboard interrupts */
/* In : */
/* Out : INTKBSR, INTKBIER */
/* local variables : */
/**************************************************************/
void init_kbi(void){
asm bset 1,INTKBSCR // mask keyboard interrupt
asm bset 5,INTKBSCR // & IRQ
asm bset 6,INTKBSCR // clear any pending IRQ request
asm bset 2,INTKBSCR // clear any pending keyboard request
asm bclr 0,INTKBSCR // keyboard interrupt triggered by falling edge only
asm bset 3,INTKBIER // enable keyboard interrupt KBD3 to wakeup from stop
// by Daytona
asm bclr 1,INTKBSCR // enable keyboard interrupts
}
/*****************************************************************************/
/* Init_ICG */
/* Description : it initializes the ICG @ 2 MHz */
/* In : */
/* Out : ICGCR, ICGMR */
/* local variables : */
/*****************************************************************************/
void init_icg(void){
ICGCR = 0x08; // mcu clk = internal clock
ICGMR = 0x1A; // mcu clk = 2.000 MHz
while(!ICGCR_ICGS); // wait for PLL stable
}
/*****************************************************************************/
/* Init_Timer */
/* Description : it initializes the timer to use the internal clock. The */
/* timer is re-configured for transmission then returns to this default. */
/* In : */
/* Out : TSC */
/* local variables : */
/*****************************************************************************/
void init_timer(void){
asm lda TSC
TSC = 0x30; //Clear & stop the timer, disable interrupts
}
/*****************************************************************************/
/* Init_ports */
/* Description : it initializes MCU ports */
/* In : */
/* Out : DDRA, DDRB */
/* local variables : */
/*****************************************************************************/
void init_ports(void){
// Initialize Tango3 control (not quite enough pins on PORTB, Mode uses PORTA)
DDRB = 0x07; // DDRB=#%00000111
// PTB0 - MODE OUTPUT
// PTB1 - ENABLE OUTPUT
// PTB2 - DATA OUTPUT
// PTB3 - DATACLK INPUT
// PTA7 - BAND OUTPUT (Initialized below)
// Initialize Daytona Control (and one pin for Tango3 control)
DDRA = 0xF6; // DDRA=#%11111100
// PTA0 - RUN STATE INPUT (prevent floating input)
// PTA1 - DOUTb INPUT
// PTA2 - S1/Vpp OUTPUT
// PTA3 - S0 OUTPUT
// PTA4 - DCLK OUTPUT
// PTA5 - DDATA OUTPUT
// PTA6 - N/C OUTPUT (prevent floating input)
// PTA7 - MODE OUTPUT (to Tango3, see above)
PTA = 0;
PTB = 0;
tango_Mode = 1; // [PTA7]Set Tango into FSK mode
tango_Band = 1; // [PTB0]Set Tango for 434/315 MHz transmission
}
//*** Place Daytona in Read Temperature Mode
void tango_read_temperature_mode(void){
S1 = 1;
S0 = 0;
}
//*** Place Daytona in Read Pressure Mode
void tango_read_pressure_mode(void){
S1 = 0;
S0 = 1;
}
//*** Place Daytona in SAMPLE Mode
void tango_read_data_out(void){
S1 = 1;
S0 = 1;
}
//*** Place Daytona in IDLE Mode
void tango_idle(void){
S1 = 0;
S0 = 0;
}
//*** Place MCU in asleep_tx Mode
void asleep_tx(void){
init_sys(); // Re-initialize all variables and KBD interrupts, and
tango_idle(); // wait for wake-up.
asm stop
}
在PRM文件设置中断地址向量