|
|
View previous topic :: View next topic |
Author |
Message |
Monk9514524 Guest
|
ADC problem with SPI and Interrupt |
Posted: Thu Nov 27, 2008 1:57 am |
|
|
HI~
I am a new C language user and work with CCS compiler.
I have an project that use Timer1 of PIC18F4620 and can't use ADC.
Here is my question:
I try to put the SPI code(from KamPutty) of Accelerometer(LIS3LV02DQ) and the ADC code of Gyro(ADXRS300) together in the same
interruption. but somehow my code can't be edited by CCS.When I only put the ADC code, the program can work very well
in the interruption. As long as I put the SPI code into it and some function, suddenly can't work anymore!
Please help me to solve my program's problem.
Code: | #include <18F4620.H> // <18F452.H> <16F877.H> // device header file from CCS-C
//#include "KamPutty.c"
#include <stdlib.h> // for function atoi(), atol(), atof(), etc.
#device ADC=10 // choose 10 bit AD instead of 8
#define CLOCK_FREQUENCY 10000000
#use delay (clock= CLOCK_FREQUENCY) // 10 MHz crystal oscillator
#use rs232 (baud = 28500, xmit= PIN_C6, rcv= PIN_C7, errors)
#define ccp2_period 2000 // CCP2_compare_match_interrupt_period
// Sampleing Time according to ccp2_period
int16 dt= 1/10 * 2 * ccp2_period;// dt = 1/10 * 2 * ccp2_period
int16 time_tick = 0; // system clock
int16 time_sec = 0; // time_tick = 10^6 / (1/10 * 2 * ccp2_period)
int16 ad_data;
#ifdef __PCM__ // PIC16Fxxx
#bit A4 = 0x05.4 // Port_A, pin #5, for CCS-C only
#bit TRISA4 = 0x85.4
#define PORTD *(int8 *)(0x08)
#define TRISD *(int8 *)(0x88)
#else // PIC18Fxxx
#bit A4 = 0xF80.4
#bit TRISA4 = 0xF92.4
#define PORTD *(int8 *)(0xF83)
#define TRISD *(int8 *)(0xF95)
#endif
// api
#define WHO_AM_I 0x0f
#define OFFSET_X 0x16
#define OFFSET_Y 0x17
#define OFFSET_Z 0x18
#define GAIN_X 0x19
#define GAIN_Y 0x1a
#define GAIN_Z 0x1b
#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define HP_FILTER_RESET 0x23
#define STATUS_REG 0x27
#define OUTX_L 0x28
#define OUTX_H 0x29
#define OUTY_L 0x2a
#define OUTY_H 0x2b
#define OUTZ_L 0x2c
#define OUTZ_H 0x2d
#define FF_WU_CFG 0x30
#define FF_WU_SRC 0x31
#define FF_WU_ACK 0x32
#define FF_WU_THS_L 0x34
#define FF_WU_THS_H 0x35
#define FF_WU_DURATION 0x36
#define DD_CFG 0x38
#define DD_SRC 0x39
#define DD_ACK 0x3a
#define DD_THSI_L 0x3c
#define DD_THSI_H 0x3d
#define DD_THSE_L 0x3e
#define DD_THSE_H 0x3f
// pin defines
#define SDO PIN_B0 // data out
#define SDI PIN_B1 // data in
#define SPC PIN_B2 // clock, high when CS=HIGH
#define CS PIN_B3 // low=enabled
/*-------------Function Zone---------------------------------------*/
int8 const bitMask8[]={
0b10000000,
0b01000000,
0b00100000,
0b00010000,
0b00001000,
0b00000100,
0b00000010,
0b00000001
};
void write_8bit_serial_data(unsigned int8 data)
void write_16bit_serial_data(unsigned int8 reg, unsigned int8 data)
unsigned int8 read_8bit_serial_data(unsigned int8 data)
void my_delay_us ( int16 n ); // roughly delay n usec using delay loop
int16 analog(int8 ch, int8 S_H_delay) // read analog input channel 'ch'
/*-----------------------Veriable Setting Zone---------------------*/
float yout=0,xin,x1=0,x2=0,x3=0,x4=0,x5=0; //濾波器用的變數
float a0=0.4 ,a1=0.25 ,a2=0.15 ,a3=0.1,aa4=0.07 ,a5=0.03 ; //濾波器參數設定
int16 yaw_rate_gyro, yaw_degree_gyro ;
int16 yaw_rate_acc , yaw_degree_acc ;
int16 X,Y,Z ;
int16 x_acc, y_acc, z_acc ;
/*-------------------------------------------------------------------*/
#INT_CCP2 // Capture/Compare ISR
void system_clock_CCP2_ISR()
{
A4 = 1; // get a scope to see this signal
CCP_2 += ccp2_period; // setup critirion for next CCP2_ISR
// CCP_2 is defined in 16F877.H
if ( ++time_tick > 1000000/dt ) { time_tick = 0; ++time_sec; }; // Counting for interrupt
/*-------------------Gyro Data Acquire and Digital Filtering------------*/
ad_data = read_adc ( ADC_READ_ONLY );
xin=ad_data; //數位濾波器
yout = a0*xin+a1*x1+a2*x2+a3*x3+aa4*x4+a5*x5;
x5=x4; //參數代換
x4=x3;
x3=x2;
x2=x1;
x1=xin;
//5mV °/s
yaw_rate_gyro=yout-524; // ( x-524 )/1024 * 5V / 0.005 (V /°/s ) 出來是角速度 °/s
//yaw_rate_gyro=(yout-524)/1024*5/0.005;
yaw_degree_gyro = yaw_rate_gyro*dt; // unit (度)
//---radius_of_turning_center
/*-----------------------End--------------------------------------------*/
/*------------Accelerometer Data Acquire -------*/
X=read_8bit_serial_data(0x29);
X<<=8;
X+=read_8bit_serial_data(0x28);
X=~X;
Y=read_8bit_serial_data(0x2b);
Y<<=8;
Y+=read_8bit_serial_data(0x2a);
Y=~Y;
Z=read_8bit_serial_data(0x2d);
Z<<=8;
Z+=read_8bit_serial_data(0x2c);
Z=~Z;
//需要delay 一下嗎
x_acc=X/1671.8;
y_acc=Y/1671.8; //+-2G設定 可改成+-6G
z_acc=Z/1671.8; //16位元 65536~ X/16384 * 1g *9.8 m /s^2=X/1671.8
//PORTD = ad_data >> 2; // 會有一個取樣週期的延遲
read_adc ( ADC_START_ONLY );
e_previous = e;
A4 = 0;
}
void main()
{
printf("\n\n\r\n PIC 中斷時鐘 與 ADC 測試,取樣頻率 = Hz ");
printf("\r\n\n 請將信號產生器接到 RA0 ");
printf("\r\n\n 請按鍵盤起動時鐘開始測試 ... 再按任意鍵就暫停列印 ... ");
printf("\r\n\n 暫停列印時,PIC 時鐘、AD 轉換及 ...");
getc();
// ----- Initialization --------------------------------------------------
// powerup device Acc
write_16bit_serial_data(0x20, 0b11000111); //原始設定是+-2G
write_16bit_serial_data(0x21, 0b00000001);
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_2 );
setup_ccp2 ( CCP_COMPARE_INT ); // configure CCP2 in COMPARE mode and ...
// CCP2 Interrupt on compare match
enable_interrupts ( INT_CCP2 );
enable_interrupts ( GLOBAL );
set_timer1(0);CCP_2=ccp2_period; // start the CCP2_ISR at 1 msec later
//setup_adc_ports ( ANALOG_AN0 ); // RA0 as analog input
setup_adc_ports(AN0_TO_AN1|VSS_VDD);
setup_adc ( ADC_CLOCK_DIV_32 ); // 32 * T_osc = 1.6 us per bit at 20 MHz
set_adc_channel ( 0 ); // select RA0 as analog input channel
TRISA4 = 0; // port A, RA4 for digital output
TRISD = 0; // 請將 8-bit DAC 接到 PORTD
output_high ( PIN_C2 );
// ----- Initialization --- finished -------------------------------------
while ( 1 )
{
while ( !kbhit() ) // press any key to get out
{
delay_ms ( 200 ); // wait 200 msec
printf("\r\n T= %lu.%04lu sec, AN0= %lu, yout=%d ", time_sec, time_tick, ad_data, yout );
//printf("\r\n T= %lu.%04lu sec, AN0= %lu ", time_sec, time_tick, ad_data);
}; getc(); // remove keyboard input
printf("\n\n\r PIC_Time = %lu.%04lu sec", time_sec, time_tick);
printf(" ... press any key ... "); getc(); // wait until key pressed
}
} |
|
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu Nov 27, 2008 3:31 am |
|
|
Your performing a lot of time consuming operations in your ISR, float arithmetic is the worst of all. Try to move all calculations to the main level or use integer multiply instead of float. |
|
|
Monk9514524 Guest
|
|
Posted: Thu Nov 27, 2008 5:07 am |
|
|
Sorry~ I forget to mention that CCS can't edit~ i can;t even put my code into PIC~ |
|
|
Monk9514524 Guest
|
|
Posted: Thu Nov 27, 2008 5:13 am |
|
|
and always stop at #device ADC=10~ |
|
|
Ttelmah Guest
|
|
Posted: Thu Nov 27, 2008 5:49 am |
|
|
In which case, simplify your code, to see what is wrong.
In the first few lines:
No fuses. You need to specify the oscillator type (HS, and some 'basic' things - NOLVP, NOXINST), before the chip can run.
The configuration (fuses, and clock settings), _must_ be in front of every include, except for the processor definition.
Learn to use the code buttons.
Code: |
#include <18F4620.H> // device header file from CCS-C
#fuses HS,NOWDT,NOLVP,NOXINST
#device ADC=10 // choose 10 bit AD instead of 8
#define CLOCK_FREQUENCY 10000000
#use delay (clock= CLOCK_FREQUENCY) // 10 MHz crystal oscillator
#use rs232 (baud = 28500, xmit= PIN_C6, rcv= PIN_C7, errors)
//End of definitions, _now_ include other stuff
//#include "KamPutty.c"
#include <stdlib.h> // for function atoi(), atol(), atof(), etc.
etc..
|
Start simpler. Just a single function, toggling a pin, to prove you are programming and running the chip, _first_.
You are setting the CCP, to interrupt every 4000 machine instructions. Even a single float multiplication, takes typically over 500 instructions. Once you get the chip working, FvM, is 'spot on'.
Note that you don't want to set the counter forward in the ISR. Using the CCP, when the special even trigger fires, it automatically resets the CCP.
You don't want to enable the CCP interrupt, but the INT_AD interrupt.
When the special even fires, it resets the CCP counter, and _starts_ the ADC automatically. You need to interrupt, when the ADC finishes.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|