|
这是我用996调试ADXL345,第一个问题是外部中断无法进入,因为是低电平触发,于是我干脆把外部中断直接接地,第二个问题,现在中断进去了,但我必须不断对SDA这条线拔出来,然后快速轻轻触碰管脚,才会有数据从串口输出。请教各位高手,我该怎么改程序才能自动进入外部中断,自动发送数据?
#include <compiler_defs.h>
#include <C8051F990_defs.h> // SFR declarations
#include "adxl.h"
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define SYSCLK 24500000 // System clock frequency in Hz
#define SMB_FREQUENCY 10000 // Target SCL clock rate
// This example supports between 10kHz
// and 100kHz
#define BAUDRATE 9600 // Baud rate of UART in bps
#define WRITE 0x00 // SMBus WRITE command
#define READ 0x01 // SMBus READ command
// Device addresses (7 bits, LSB is a don't care)
#define SLAVE_ADDR 0xA6 // Device address for slave target
// Status vector - top 4 bits only
#define SMB_MTSTA 0xE0 // (MT) start transmitted
#define SMB_MTDB 0xC0 // (MT) data byte transmitted
#define SMB_MRDB 0x80 // (MR) data byte received
// End status vector definition
//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------
U8 SMB_DATA_IN1; // Global holder for SMBus data
// All receive data is written here
U8 SMB_DATA_IN2;
U8 SMB_DATA_OUT1; // Global holder for SMBus data.
U8 SMB_DATA_OUT2; // Global holder for SMBus data.
// All transmit data is read from here
U8 TARGET; // Target SMBus slave address
volatile bit SMB_BUSY; // Software flag to indicate when the
// SMB_Read() or SMB_Write() functions
// have claimed the SMBus
volatile bit SMB_RW; // Software flag to indicate the
// direction of the current transfer
U16 NUM_ERRORS; // Counter for the number of errors.
unsigned char transfer;
SBIT (YELLOW_LED, SFR_P0, 3); // YELLOW_LED==LED_ON means ON
SBIT (SDA, SFR_P0, 0); // SMBus on P0.0
SBIT (SCL, SFR_P0, 1); // and P0.1
LOCATED_VARIABLE_NO_INIT (reserved, U8, SEG_XDATA, 0x0000);
bit byte1,byte2,byte3;//表示有效的字节
char x[2],y[2],z[2];//分别存储传过来的
int x_data,y_data,z_data;
char send_data1,send_data2,send_data3;
char rec_data1,rec_data2;
char test;
unsigned char P3;
U8 TX_Ready =1;
// SMBus Interrupt Service Routine (ISR)
//-----------------------------------------------------------------------------
//
// SMBus ISR state machine
// - Master only implementation - no slave or arbitration states defined
// - All incoming data is written to global variable <SMB_DATA_IN>
// - All outgoing data is read from global variable <SMB_DATA_OUT>
//
//-----------------------------------------------------------------------------
INTERRUPT(SMBUS0_ISR, INTERRUPT_SMBUS0)
{
bit FAIL = 0; // Used by the ISR to flag failed
// transfers
static bit ADDR_SEND = 0; // Used by the ISR to flag byte
static bit REG_SEND = 0; //
// transmissions as slave addresses
if (ARBLOST == 0) // Check for errors
{
// Normal operation
switch (SMB0CN & 0xF0) // Status vector
{
// Master Transmitter/Receiver: START condition transmitted.
case SMB_MTSTA:
SMB0DAT = TARGET; // Load address of the target slave
SMB0DAT &= 0xFE; // Clear the LSB of the address for the
// R/W bit
SMB0DAT |= SMB_RW; // Load R/W bit
STA = 0; // Manually clear START bit
ADDR_SEND = 1;
break;
// Master Transmitter: Data byte transmitted
case SMB_MTDB:
if (ACK) // Slave ACK?
{
if (ADDR_SEND) // If the previous byte was a slave
{ // address,
ADDR_SEND = 0; // Next byte is not a slave address
if (SMB_RW == WRITE) // If this transfer is a WRITE,
{
// send data byte
SMB0DAT = SMB_DATA_OUT1;
REG_SEND=1; //
}
else {} // If this transfer is a READ,
// proceed with transfer without
// writing to SMB0DAT (switch
// to receive mode)
}
else // If previous byte was not a slave
{ // address,
if(transfer==1) // If transfer is a receive
{
SMB_BUSY = 0; // free SMBus
}
else // If transfei is a transmitt
{
if(REG_SEND) // If the previous byte was a register address
{
SMB0DAT = SMB_DATA_OUT1;
REG_SEND=0;
}
else // If the previous byte was a data,
{
STO = 1; // send a STOP
SMB_BUSY = 0;
}
}
}
}
else // If slave NACK,
{
STO = 1; // Send STOP condition, followed
STA = 1; // By a START
NUM_ERRORS++; // Indicate error
}
break;
// Master Receiver: byte received
case SMB_MRDB:
if(byte1==1)
{
SMB_DATA_IN1 = SMB0DAT;
byte1=0;
if(byte2==1)
ACK=1;
else ACK=0;
}
else if(byte2==1)
{
SMB_DATA_IN2 = SMB0DAT;
byte2=0;
ACK=0;
}
else
ACK = 0; // Send NACK to indicate last byte
// of this transfer
STO = 1; // Send STOP to terminate transfer
SMB_BUSY = 0; // Free SMBus interface
break;
default:
FAIL = 1; // Indicate failed transfer
// and handle at end of ISR
break;
} // end switch
}
else
{
// ARBLOST = 1, error occurred... abort transmission
FAIL = 1;
} // end ARBLOST if
if (FAIL) // If the transfer failed,
{
SMB0CF &= ~0x80; // Reset communication
SMB0CF |= 0x80;
STA = 0;
STO = 0;
ACK = 0;
SMB_BUSY = 0; // Free SMBus
FAIL = 0;
NUM_ERRORS++; // Indicate an error occurred
}
SI = 0; // Clear interrupt flag
}
//-----------------------------------------------------------------------------
// Timer3 Interrupt Service Routine (ISR)
//-----------------------------------------------------------------------------
//
// A Timer3 interrupt indicates an SMBus SCL low timeout.
// The SMBus is disabled and re-enabled here
//
//-----------------------------------------------------------------------------
/*INTERRUPT(TIMER3_ISR, INTERRUPT_TIMER3)
{
SMB0CF &= ~0x80; // Disable SMBus
SMB0CF |= 0x80; // Re-enable SMBus
TMR3CN &= ~0x80; // Clear Timer3 interrupt-pending flag
STA = 0;
SMB_BUSY = 0; // Free SMBus
}
*/
void SMB_Write(void)
{
while (SMB_BUSY); // Wait for SMBus to be free.
SMB_BUSY = 1; // Claim SMBus (set to busy)
SMB_RW = 0; // Mark this transfer as a WRITE
STA = 1; // Start transfer
}
void Send_single(char reg_addr,char send_data)
{
while (SMB_BUSY);
TARGET = SLAVE_ADDR; // Target the F3xx/Si8250 Slave for next
// SMBus transfer
SMB_DATA_OUT1 = reg_addr; // Define next outgoing byte
SMB_DATA_OUT2 = send_data; // Define next outgoing byte
transfer=0;
SMB_Write(); // Initiate SMBus write
while (SMB_BUSY);
transfer=1;
}
void SMB_Read (void)
{
while (SMB_BUSY != 0); // Wait for transfer to complete
SMB_BUSY = 1; // Claim SMBus (set to busy)
SMB_RW = 1; // Mark this transfer as a READ
STA = 1; // Start transfer
while (SMB_BUSY); // Wait for transfer to complete
}
void Rec_single(char reg_addr,char *data1)
{ //while(SMB_BUSY);
byte1=1;
byte2=0;
STA=1;
SMB_DATA_OUT1 = reg_addr; // Define next outgoing byte
TARGET = SLAVE_ADDR; // Target the F3xx/Si8250 Slave for next
// SMBus transfer
SMB_Write(); // Initiate SMBus write
STA=1;
TARGET = SLAVE_ADDR; // Target the F3xx/Si8250 Slave for next
// SMBus transfer
SMB_Read();
*data1=SMB_DATA_IN1;
}
void Rec_double(char reg_addr,char *data1,char *data2) //datasheet说最好支持突发读(多字节读)
{ STA=1;
SMB_DATA_OUT1 = reg_addr; // Define next outgoing byte
TARGET = SLAVE_ADDR; // Target the F3xx/Si8250 Slave for next
// SMBus transfer
SMB_Write(); // Initiate SMBus write
TARGET = SLAVE_ADDR; // Target the F3xx/Si8250 Slave for next
STA=1;
// P0&=0XF7;
// ADXL345_Start();
while(SMB_BUSY);
SMB_BUSY=1;
SMB_RW=1;
// SMB0CN=0X44;
byte1=1;
byte2=1;
byte3=0;//两个比特
STA=1;
while(SMB_BUSY);
*data1=SMB_DATA_IN1;
*data2=SMB_DATA_IN2;
}
void uart0() interrupt 4
{
TI0=0;//接收结束
}
void uart_int(unsigned int a)//专门用来传13位数的
{
if(a>0x1000)
{
a=0x2000-a;//转换为补码,输出符号
SBUF0='-';
while(TI0==0);
TI0=0;
}
SBUF0=a/1000+'0';
while(TI0==0);
TI0=0;
a%=1000;
SBUF0=a/100+'0';
while(TI0==0);
TI0=0;
a%=100;
SBUF0=a/10+'0';
while(TI0==0);
TI0=0;
a%=10;
SBUF0=a+'0';
while(TI0==0);
TI0=0;
}
void int0() interrupt 0
{
/* Rec_double(OFSX,&x[0],&x[1]);
Rec_single(OFSX,&y[0]);
Rec_single(OFSY,&y[1]);
SBUF0=x[1];
while(TI0==0);
TI0=0;
SBUF0=x[0];
while(TI0==0);
TI0=0;
SBUF0=y[1];
while(TI0==0);
TI0=0;
SBUF0=y[0];
while(TI0==0);
TI0=0;
SBUF0=0xcc;
while(TI0==0);
TI0=0; */
Rec_double(DATAX0,&x[0],&x[1]);
Rec_double(DATAY0,&y[0],&y[1]);
Rec_double(DATAZ0,&z[0],&z[1]);
x_data=(unsigned int)x[1];
x_data<<=8;//左移8位
x_data+=(unsigned int )x[0];//加上低8位
x_data&=0x1fff;//清除高3位无用的
y_data=(unsigned int)y[1];
y_data<<=8;//左移8位
y_data+=(unsigned int )y[0];//加上低8位
y_data&=0x1fff;//清除高3位无用的
z_data=(unsigned int)z[1];
z_data<<=8;//左移8位
z_data+=(unsigned int )z[0];//加上低8位
z_data&=0x1fff;//清除高3位无用的
SBUF0='X';
while(TI0==0);
TI0=0;
SBUF0=':';
while(TI0==0);
TI0=0;
uart_int(x_data);
SBUF0=' ';
while(TI0==0);
TI0=0;
SBUF0='Y';
while(TI0==0);
TI0=0;
SBUF0=':';
while(TI0==0);
TI0=0;
uart_int(y_data);
SBUF0=' ';
while(TI0==0);
TI0=0;
SBUF0='Z';
while(TI0==0);
TI0=0;
SBUF0=':';
while(TI0==0);
TI0=0;
uart_int(z_data);
SBUF0='\n';
while(TI0==0);
TI0=0;
/* Rec_single(DATAX0,&x[0]);
Rec_single(DATAX1,&x[1]);
Rec_single(DATAY0,&y[0]);
Rec_single(DATAY1,&y[1]);
Rec_single(DATAZ0,&z[0]);
Rec_single(DATAZ1,&z[1]);
SBUF0=x[1];
while(TI0==0);
TI0=0;
SBUF0=x[0];
while(TI0==0);
TI0=0;
SBUF0=y[1];
while(TI0==0);
TI0=0;
SBUF0=y[0];
while(TI0==0);
TI0=0;
SBUF0=z[1];
while(TI0==0);
TI0=0;
SBUF0=z[0];
while(TI0==0);
TI0=0;
SBUF0=0xcc; //表示结束
while(TI0==0);
TI0=0; */
//使中断清零
Rec_single(INT_SOURCE,&test);//通过读该寄存器使中断清零
} //直到传完
void adsl_init()
{
Send_single(DATA_FORMAT,0x2B); //数据通信格式;设置为自检功能禁用,4线制SPI接口,低电平中断输出,13位全分辨率,输出数据右对齐,16g量程
Send_single(OFSX,0x00); //X轴误差补偿; (15.6mg/LSB)
Send_single(OFSY,0x00); //Y轴误差补偿; (15.6mg/LSB)
Send_single(OFSZ,0x00); //Z轴误差补偿; (15.6mg/LSB)
Send_single(DUR,0x00); //敲击延时0:禁用; (1.25ms/LSB)
Send_single(Latent,0x00); //检测第一次敲击后的延时0:禁用; (1.25ms/LSB)
Send_single(Window,0x00); //敲击窗口0:禁用; (1.25ms/LSB)
Send_single(THRESH_ACK,0x01); //保存检测活动阀值; (62.5mg/LSB)
Send_single(THRESH_INACT,0x01); //保存检测静止阀值; (62.5mg/LSB)
Send_single(TIME_INACT,0x2B); //检测活动时间阀值; (1s/LSB)
Send_single(THRESH_FF,0x09); //自由落体检测推荐阀值; (62.5mg/LSB)
Send_single(TIME_FF,0xFF); //自由落体检测时间阀值,设置为最大时间; (5ms/LSB)
Send_single(TAP_AXES,0x80); //单击/双击轴控制)
Send_single(BW_RATE,0x0a); //100Hz的输出数据速率
Send_single(ACT_INACT_CTL,0x66); //直流耦合工作模式下 X,Y,Z三轴使能
//Send_single(ACT_INACT_CTL,0x00); //轴使能控制活动和静止检测
// Send_single(DATA_FORMAT,0X0B); //中断高电平有效
// Send_single(DATA_FORMAT,0X20); //
Send_single (FIFO_CTL,0x86); //FIFO的初始化
Send_single(INT_ENABLE,0x80); //使能数据产生中断
Send_single(INT_MAP,0x00); //该中断映射到INT1脚
Send_single(POWER_CTL,0x28); //这个一定要放在初始化的最后,都配置完了,再使能测量位 要在休眠模式下配置SFR
}
void Timer_Init()
{
// Make sure the Timer can produce the appropriate frequency in 8-bit mode
// Supported SMBus Frequencies range from 10kHz to 100kHz. The CKCON register
// settings may need to change for frequencies outside this range.
/*#if ((SYSCLK/SMB_FREQUENCY/3) < 255)
#define SCALE 1
CKCON |= 0x08; // Timer1 clock source = SYSCLK
#elif ((SYSCLK/SMB_FREQUENCY/4/3) < 255)
#define SCALE 4
CKCON |= 0x01;
CKCON &= ~0x0A; // Timer1 clock source = SYSCLK / 4
#endif
*/
CKCON = 0x08;
TMOD = 0x20; // Timer1 in 8-bit auto-reload mode
TCON = 0X40;// &= 0xFE;
// Timer1 configured to overflow at 1/3 the rate defined by SMB_FREQUENCY
TH1 = 0XBF;//(unsigned char) -(SYSCLK/SMB_FREQUENCY/SCALE/3);
TL1 = TH1; // Init Timer1
TR1 = 1; // Timer1 enabled
}
/*
void Timer3_Init (void)
{
TMR3CN = 0x00; // Timer3 configured for 16-bit auto-
// reload, low-byte interrupt disabled
CKCON &= ~0x40; // Timer3 uses SYSCLK/12
TMR3RL = (unsigned int) -(SYSCLK/12/40); // Timer3 configured to overflow after
TMR3 = TMR3RL; // ~25ms (for SMBus low timeout detect):
// 1/.025 = 40
EIE1 |= 0x80; // Timer3 interrupt enable
TMR3CN |= 0x04; // Start Timer3
}*/
void UART_Init() //使用串口0
{
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 &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
#elif (SYSCLK/BAUDRATE/2/256 < 4)
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x01;
#elif (SYSCLK/BAUDRATE/2/256 < 12)
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
#else
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
#endif
TL1 = TH1; // init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TX_Ready = 1; // Flag showing that UART can transmit
// IP |= 0x10; // Make UART high priority
// ES0 = 1; // Enable UART0 interrupts
}
void SMBus_Init()
{
SMB0CF = 0x5D; // Use Timer1 overflows as SMBus clock
// source;
// Disable slave mode;
// Enable setup & hold time
// extensions;
// Enable SMBus Free timeout detect;
// Enable SCL low timeout detect;
SMB0CF |= 0x80; // Enable SMBus;
}
void Port_IO_Init()
{
// P0.4 - TX0 (UART0), Push-Pull, Digital
// P0.5 - RX0 (UART0), Open-Drain, Digital
// P0.0 - SDA (SMBus), Open-Drain, Digital
// P0.1 - SCL (SMBus), Push-Pull, Digital
// P0.3 - INT0 (Tmr0), Open-Drain, Digital
XBR0 = 0x05;
XBR1 = 0x20;
XBR2 = 0x40;
P0MDOUT = 0x12; // All P0 pins open-drain output
IT01CF = 0x03; // /INT0 available at P0.3.低电平触发
P0MDOUT |= 0x10; // Enable UTX as push-pull output
P0=0x08;//00001000先把INT0脚拉高
P0MDIN |=0X01;
}
void Oscillator_Init()
{
REG0CN |= 0x10; // Enable the precision osc. bias
OSCICN |= 0x80; // Enable the precision internal osc.
RSTSRC = 0x04; // Enable missing clock detector and
// leave VDD Monitor enabled.
CLKSEL = 0x00; // Select precision internal osc.
// divided by 1 as the system clock
}
void Interrupts_Init()
{
IE = 0x11;//给串口0中断和外部中断的使能标志位置1
IP = 0x10;//串口的优先级置1,外部优先级置0
EIE1 = 0x01;//允许SMBUS中断
EIP1 = 0x01;//SMBUS中断为高优先级
EX0=0;
ES0=0;
EA=1;
}
// Initialization function for device,
// Call Init_Device() from your main program
void Init_Device(void)
{
Timer_Init();
// Timer3_Init();
UART_Init();
SMBus_Init();
Port_IO_Init();
Oscillator_Init();
Interrupts_Init();
}
void main()
{
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer)
// Dummy variable counters
Init_Device();
adsl_init();//芯片初始化
EX0=1;
while(1)
SBUF0='A';//测试串口
}
} |
阿莫论坛20周年了!感谢大家的支持与爱护!!
你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。
|