Ðề tài: Giao tiếp I2C
View Single Post
Old 09-12-2010, 04:03 PM   #169
winphys03
Nhập môn đệ tử
 
Tham gia ngày: Apr 2008
Bài gửi: 1
:
I2C đọc từ slave về master

Các bác giúp gửi giá trị của thang ghi POSCNTH, POSCNTL từ slave lên master với

Code Master:

#include <18f4431.h>
#include <stdlib.h>
#include <math.h>
#include <def_4431.c>
#FUSES NOWDT, HS, NOPUT, NOPROTECT
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bi ts=8)
#use I2C(MASTER,SDA=PIN_D2,SCL=PIN_D3)
#define slave 0x10
///////////////////////////////////////////////////////////////
///////////////////////Khai bao bien PID//////////////////////
int16 read;
int8 v=0,high,low;
int16 PWM;
int16 feedback_value = 0,real_v;
/////////////////////////////////////////////////////////////
/////////////////////////Nhan du lieu tu may tinh////////////
#INT_RDA
void getvalue()
{
int i;
char s[3];
for(i=0;i<3;i++)
s[i]=getc();
v=atol(s);
}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
int16 read_I2C_2byte(int8 slave_address)
{
int16 value_read;
i2c_start();
i2c_write(slave_address+1);
high=i2c_read(1);
delay_us(10);
low=i2c_read(0);
i2c_stop();
value_read=make16(high,low);
value_read=value_read/5.2;
printf(" %Ld\n\r",value_read);
return value_read;
}
//////////////////////Setup QEI/////////////////////////////////
void setup_QEI()
{
QEICON = QEI_4XPER | VELOCITY_DIV_4;
QEICON = 0b11011011;
MAXCNT = 800;
POSCNT = 0;
POSCNTH = 0; // High byte of 16-bit encoder count
POSCNTL = 0; // low byte
CAP1CON = 0b010011000;
DFLTCON = 0b01110010;
setup_timer_5 (T5_INTERNAL | T5_DIV_BY_4);
}
//////////////////////////////////////////////////////////
//////////////////Read Encoder///////////////////////////
#INT_TIMER1
void read_encoder()
{
set_timer1(32875);
read = POSCNT;
POSCNT=0;
real_v = read/5.2;
read=0;
}
/////////////////////////////////////////////////////////
////////////////////PID Control/////////////////////////
void pidcontrol()
{
unsigned char kp = 2;
unsigned char ki = 0.000003;
unsigned char kd = 0.005;
int16 set_value = 0;
int16 delta_t=0.0065;
signed long error_value = 0;
static signed long pre_error = 0;
static signed long integral = 0;
signed long derivative = 0;
feedback_value = real_v;
set_value = v;
error_value = set_value -feedback_value;
integral = integral + error_value;
derivative = (error_value - pre_error)/delta_t;
PWM = PWM+ (kp * error_value) + (ki * integral) + (kd * derivative);
if (PWM > 1020)
{ PWM = 1020; }
else if (PWM < -1020)
{PWM = -1020;}
pre_error = error_value;
}

///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

void main()
{
int16 value_read;
delay_ms(500);
setup_QEI();
enable_interrupts(INT_RDA);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DIV_BY_1,255,1);
setup_ccp2(CCP_PWM);
set_pwm2_duty(0);
set_timer1(32875);
while(true)
{
pidcontrol();
set_pwm2_duty(PWM);
value_read=read_I2C_2byte(slave);
}
}

Code Slave
#include <18f4431.h>
#include <stdlib.h>
#include <math.h>
#include <def_4431.c>
#FUSES NOWDT, HS, NOPUT, NOPROTECT
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bi ts=8)
#use I2C(SLAVE,SDA=PIN_D2,SCL=PIN_D3,address=0x10,fast= 500000,force_hw)
///////////////////////////////////////////////////////////////
///////////////////////Khai bao bien PID//////////////////////
int8 value_read;
int16 read;
int16 PWM;
int16 feedback_value = 0,real_v;
///////////////////////////////////////////////////////////

//////////////////////Setup QEI/////////////////////////////////
void setup_QEI()
{
QEICON = QEI_4XPER | VELOCITY_DIV_4;
QEICON = 0b11011011;
MAXCNT = 800;
POSCNT = 0;
POSCNTH = 0; // High byte of 16-bit encoder count
POSCNTL = 0; // low byte
CAP1CON = 0b010011000;
DFLTCON = 0b01110010;
setup_timer_5 (T5_INTERNAL | T5_DIV_BY_4);
}
//////////////////////////////////////////////////////////
//////////////////Read Encoder///////////////////////////
#INT_TIMER1
void read_encoder()
{
set_timer1(32875);
read = POSCNT;
POSCNT=0;
real_v = read/5.2;
read=0;
}
/////////////////////////////////////////////////////////
////////////////////Send to Master/////////////////////////
#INT_SSP
void i2c_isr()
{
int8 state;
state = i2c_isr_state();

if(state<0x80)
value_read = i2c_read();


if(state>=0x80)
{
if (state==0x80)
i2c_write(POSCNTH);
if (state==0x81)
i2c_write(POSCNTL);

}
}

////////////////////////////////////////////////////////////////
////////////////////PID Control/////////////////////////
void pidcontrol()
{
unsigned char kp = 2;
unsigned char ki = 0.000003;
unsigned char kd = 0.005;
int16 set_value = 0;
int16 delta_t=0.0065;
signed long error_value = 0;
static signed long pre_error = 0;
static signed long integral = 0;
signed long derivative = 0;
feedback_value = real_v;
set_value = 20;
error_value = set_value -feedback_value;
integral = integral + error_value;
derivative = (error_value - pre_error)/delta_t;
PWM = PWM+ (kp * error_value) + (ki * integral) + (kd * derivative);
if (PWM > 1020)
{ PWM = 1020; }
else if (PWM < -1020)
{PWM = -1020;}
pre_error = error_value;
}

///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

void main()
{

setup_QEI();
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DIV_BY_1,255,1);
setup_ccp2(CCP_PWM);
set_pwm2_duty(0);
set_timer1(32875);
while(true)
{
pidcontrol();
set_pwm2_duty(PWM);
delay_ms(100);
}
}
winphys03 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn