|
|
View previous topic :: View next topic |
Author |
Message |
PICLeo
Joined: 14 Dec 2005 Posts: 11 Location: South Africa
|
18F242 change from 3.278MHz to 20Mhz |
Posted: Fri Feb 17, 2006 1:55 am |
|
|
Hi
I do have a program that connects 3 18F242 Pics via I2c. At the moment all three pics are working with a 3.278Mhz crystal. Because of the reason that I do a lot of calculation with one of the slaves, takes almost 5ms, I want to change the crystals to 20Mhz. I do have the problem that I am getting calculation mistakes from time to time. I think that it just needs to much time to calculate the various values so that the PIC is might be to slow. The I2C is working quite well.
If I change the crystals to one of those 20 Mhz ones the Pics tend to restart all the time. I changed the frequenzy to the 20Mhz and use HS within the header file.
What else can there be wrong? I think it has something to do with the I2C but I dont understand why.
Here the codes. I know its quite a lot but maybe somebody can help me.
MASTER: Code: | #include <MASTER.h>
#include <stdlib.h>
void write_slave1(byte slave_address);
void read_slave1(byte slave_address);
void read_slave2(byte slave_address);
void send_RS232();
void receive_RDA();
#define slave1_address 0x02
#define slave2_address 0x04
#define BUFFER_SIZE 16
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
char inputstring[16];
int8 RTCCi = 0;
int1 transmit = 0;
int1 RDAset = 0;
char inputchar;
signed int8 angle_in = 0;
union speed_bytes
{
float speed_in;
int8 speed_in_byte[4];
} speed_value;
union acceleration_bytes
{
float acceleration_in;
int8 acceleration_in_byte[4];
} acceleration_value;
union distance_bytes
{
float distance_in;
int8 distance_in_byte[4];
} distance_value;
#int_RTCC
RTCC_isr()
{
if(RTCCi == 19)
{
transmit = 1;
RTCCi = 0;
}
else RTCCi++;
}
#int_RDA
RDA_isr()
{
inputchar = getc();
if(inputchar == 0x0d)
{
RDAset = 1;
}
else
{
buffer[next_in] = inputchar;
if (next_in < BUFFER_SIZE)
next_in = (next_in + 1);
}
}
void write_slave1(byte slave_address)
{
i2c_start();
delay_ms(1);
i2c_write(slave_address);
delay_ms(1);
i2c_write(inputstring[4]);
delay_ms(1);
i2c_write(inputstring[5]);
delay_ms(1);
i2c_write(inputstring[6]);
delay_ms(1);
i2c_write(inputstring[7]);
delay_ms(1);
i2c_stop();
}
void write_slave2(byte slave_address)
{
i2c_start();
delay_ms(1);
i2c_write(slave_address);
delay_ms(1);
i2c_write(inputstring[1]);
delay_ms(1);
i2c_write(inputstring[2]);
delay_ms(1);
i2c_write(inputstring[3]);
delay_ms(1);
i2c_stop();
}
void read_slave1(byte slave_address)
{
i2c_start();
delay_ms(1);
i2c_write(slave_address + 1);
speed_value.speed_in_byte[0] = i2c_read(1);
speed_value.speed_in_byte[1] = i2c_read(1);
speed_value.speed_in_byte[2] = i2c_read(1);
speed_value.speed_in_byte[3] = i2c_read(1);
acceleration_value.acceleration_in_byte[0] = i2c_read(1);
acceleration_value.acceleration_in_byte[1] = i2c_read(1);
acceleration_value.acceleration_in_byte[2] = i2c_read(1);
acceleration_value.acceleration_in_byte[3] = i2c_read(1);
distance_value.distance_in_byte[0] = i2c_read(1);
distance_value.distance_in_byte[1] = i2c_read(1);
distance_value.distance_in_byte[2] = i2c_read(1);
distance_value.distance_in_byte[3] = i2c_read(0);
i2c_stop();
}
void read_slave2(byte slave_address)
{
i2c_start();
delay_ms(1);
i2c_write(slave_address + 1);
angle_in = i2c_read(0);
i2c_stop();
}
void send_RS232()
{
read_slave1(slave1_address);
read_slave2(slave2_address);
printf("%2.1f,%2.1f,%3.1f,%d\n",speed_value.speed_in,acceleration_value.acceleration_in,distance_value.distance_in,angle_in);
transmit = 0;
}
void receive_RDA()
{
disable_interrupts(INT_RDA);
strncpy (inputstring, buffer, 16);
next_in = 0;
RDAset = 0;
enable_interrupts(INT_RDA);
write_slave1(slave1_address);
write_slave2(slave2_address);
}
void initialize()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32|RTCC_8_bit);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
enable_interrupts(INT_RTCC);
enable_interrupts(INT_RDA);
enable_interrupts(global);
}
void main()
{
output_high(PIN_B4);
delay_ms(500);
output_low(PIN_B4);
initialize();
while(1)
{
if(transmit == 1)
{
send_RS232();
}
If(RDAset == 1)
{
receive_RDA();
}
}
}
|
SLAVE1: Code: | #include <SLAVE1.h>
#include <stdlib.h>
unsigned char read_i2c(void);
void write_i2c(unsigned char transmit_byte);
void i2c_interrupt_handler(void);
void initialize(void);
void i2c_error(void);
void write_i2c(unsigned char transmit_byte);
void hand();
void speed_control();
void calculation_speed();
void calculation_acceleration();
void calculation_distance();
/* Bit defines */
#define PIC_SSPSTAT_BIT_SMP 0x80
#define PIC_SSPSTAT_BIT_CKE 0x40
#define PIC_SSPSTAT_BIT_DA 0x20
#define PIC_SSPSTAT_BIT_P 0x10
#define PIC_SSPSTAT_BIT_S 0x08
#define PIC_SSPSTAT_BIT_RW 0x04
#define PIC_SSPSTAT_BIT_UA 0x02
#define PIC_SSPSTAT_BIT_BF 0x01
#define PIC_SSPCON1_BIT_WCOL 0x80
#define PIC_SSPCON1_BIT_SSPOV 0x40
#define PIC_SSPCON1_BIT_SSPEN 0x20
#define PIC_SSPCON1_BIT_CKP 0x10
#define PIC_SSPCON1_BIT_SSPM3 0x08
#define PIC_SSPCON1_BIT_SSPM2 0x04
#define PIC_SSPCON1_BIT_SSPM1 0x02
#define PIC_SSPCON1_BIT_SSPM0 0x01
#define PIC_SSPCON2_BIT_GCEN 0x80
#define PIC_SSPCON2_BIT_ACKSTAT 0x40
#define PIC_SSPCON2_BIT_ACKDT 0x20
#define PIC_SSPCON2_BIT_ACKEN 0x10
#define PIC_SSPCON2_BIT_RCEN 0x08
#define PIC_SSPCON2_BIT_PEN 0x04
#define PIC_SSPCON2_BIT_RSEN 0x02
#define PIC_SSPCON2_BIT_SEN 0x01
/* Byte Reg defines*/
#byte PIC_SSPBUF=0xFC9
#byte PIC_SSPADD=0xFC8
#byte PIC_SSPSTAT=0xFC7
#byte PIC_SSPCON1=0xFC6
#byte PIC_SSPCON2=0xFC5
#define RX_BUF_LEN 5
#define NODE_ADDR 0x02
unsigned char slave_buffer[RX_BUF_LEN];
unsigned char speed_string[RX_BUF_LEN];
float buffer_speed[2];
int buffer_index;
int8 hallwheel = 0;
int8 hallwheelbuffer = 0;
int8 hallgear = 0;
int8 hallgearbuffer = 0;
int16 hallwheelcount = 0;
int8 speedin = 0;
int16 speedin1 = 0;
int16 speedin2 = 0;
int16 speedin3 = 0;
int8 i = 0;
int8 ii = 0;
union speed_bytes
{
float speed_out;
int8 speed_out_byte[4];
} speed_value;
union acceleration_bytes
{
float acceleration_out;
int8 acceleration_out_byte[4];
} acceleration_value;
union distance_bytes
{
float distance_out;
int8 distance_out_byte[4];
} distance_value;
#INT_SSP
void ssp_interupt ()
{
hand();
}
#int_ext
EXT_isr()
{
if(Input(PIN_B0) == 1)
{
hallwheel++;
}
}
#int_RTCC
RTCC_isr()
{
if(i == 49)
{
calculation_speed();
calculation_acceleration();
calculation_distance();
i = 0;
}
else
{
i++;
}
}
void hand()
{
unsigned char i2c_mask = 0x2D; /* 0010 1101 */
byte temp_sspstat;
unsigned char this_byte;
unsigned char tx_byte;
int x;
temp_sspstat = PIC_SSPSTAT & i2c_mask;
switch(temp_sspstat)
{
case 0x09:
for (x=0; x<RX_BUF_LEN; x++)
{
slave_buffer[x]=0x00;
}
buffer_index=0;
this_byte = read_i2c();
break;
case 0x29:
this_byte = read_i2c();
slave_buffer[buffer_index] = this_byte;
if (buffer_index == 3)
{
speed_control();
}
buffer_index++;
if (buffer_index >= RX_BUF_LEN)
{
buffer_index = 0;
}
break;
case 0x0c:
write_i2c(speed_value.speed_out_byte[0]);
break;
case 0x2c:
write_i2c(speed_value.speed_out_byte[1]);
write_i2c(speed_value.speed_out_byte[2]);
write_i2c(speed_value.speed_out_byte[3]);
write_i2c(acceleration_value.acceleration_out_byte[0]);
write_i2c(acceleration_value.acceleration_out_byte[1]);
write_i2c(acceleration_value.acceleration_out_byte[2]);
write_i2c(acceleration_value.acceleration_out_byte[3]);
write_i2c(distance_value.distance_out_byte[0]);
write_i2c(distance_value.distance_out_byte[1]);
write_i2c(distance_value.distance_out_byte[2]);
write_i2c(distance_value.distance_out_byte[3]);
break;
}
}
void speed_control()
{
ii++;
strncpy (speed_string, slave_buffer, 8);
if(ii <= 5)
{
}
else
{
ii=10;
if(speed_string[0] == '0')
{
speedin3 = ((speed_string[1] - 0x30) * 100);
speedin2 = ((speed_string[2] - 0x30) * 10);
speedin1 = (speed_string[3] - 0x30);
speedin = speedin3 + speedin2 + speedin1;
set_pwm1_duty(speedin);
set_pwm2_duty(0);
}
if(speed_string[0] == '1')
{
speedin3 = ((speed_string[1] - 0x30) * 100);
speedin2 = ((speed_string[2] - 0x30) * 10);
speedin1 = (speed_string[3] - 0x30);
speedin = speedin3 + speedin2 + speedin1;
set_pwm1_duty(0);
set_pwm2_duty(speedin);
}
}
}
void calculation_speed()
{
hallwheelbuffer = hallwheel;
hallwheel = 0;
hallwheelcount = hallwheelcount + hallwheelbuffer;
speed_value.speed_out = (hallwheelbuffer * 0.02) / 0.2;
buffer_speed[1] = buffer_speed[0];
buffer_speed[0] = speed_value.speed_out;
}
void calculation_acceleration()
{
acceleration_value.acceleration_out = (buffer_speed[0] - buffer_speed[1])/0.2;
}
void calculation_distance()
{
distance_value.distance_out = hallwheelcount * 0.02;
}
void initialize(void)
{
int i = 0;
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32|RTCC_8_bit);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_16,255,1);
setup_ccp1(CCP_PWM);
setup_ccp2(CCP_PWM);
set_pwm1_duty(0);
set_pwm2_duty(0);
set_tris_a(0b00000000);
set_tris_b(0b00000111);
set_tris_c(0b00011000);
PIC_SSPCON1 = 0x36;
PIC_SSPADD = NODE_ADDR;
PIC_SSPSTAT = 0x00;
enable_interrupts(INT_SSP);
enable_interrupts(INT_EXT);
enable_interrupts(INT_EXT1);
enable_interrupts(INT_RTCC);
ext_int_edge(L_TO_H);
ext_int_edge(1, L_TO_H);
for (i=0; i<RX_BUF_LEN; i++)
{
speed_string[i]=0x00;
}
buffer_speed[1]=0;
buffer_speed[0]=0;
speed_value.speed_out_byte[0] = 0;
speed_value.speed_out_byte[1] = 0;
speed_value.speed_out_byte[2] = 0;
speed_value.speed_out_byte[3] = 0;
speed_value.speed_out = 0;
acceleration_value.acceleration_out_byte[0] = 0;
acceleration_value.acceleration_out_byte[1] = 0;
acceleration_value.acceleration_out_byte[2] = 0;
acceleration_value.acceleration_out_byte[3] = 0;
acceleration_value.acceleration_out = 0;
distance_value.distance_out_byte[0] = 0;
distance_value.distance_out_byte[1] = 0;
distance_value.distance_out_byte[2] = 0;
distance_value.distance_out_byte[3] = 0;
distance_value.distance_out = 0;
output_high(PIN_B4);
delay_ms(200);
output_low(PIN_B4);
}
unsigned char read_i2c(void)
{
return PIC_SSPBUF;
}
void write_i2c(unsigned char transmit_byte)
{
unsigned char write_collision = 1;
while (PIC_SSPSTAT & PIC_SSPSTAT_BIT_BF)
{
}
while (write_collision)
{
PIC_SSPCON1 &= ~PIC_SSPCON1_BIT_WCOL;
PIC_SSPBUF = transmit_byte;
if(PIC_SSPCON1 & PIC_SSPCON1_BIT_WCOL)
{
write_collision = 1;
}
else
{
write_collision = 0;
}
}
PIC_SSPCON1 |= PIC_SSPCON1_BIT_CKP;
}
void main()
{
initialize();
enable_interrupts(GLOBAL);
while (1)
{
}
}
|
SLAVE2: Code: |
#include <SLAVE2.h>
#include <stdlib.h>
unsigned char read_i2c(void);
void write_i2c(unsigned char transmit_byte);
void i2c_interrupt_handler(void);
void initialize(void);
void i2c_error(void);
void write_i2c(unsigned char transmit_byte);
void hand();
void steering_control();
void calculation_angle();
/* Bit defines */
#define PIC_SSPSTAT_BIT_SMP 0x80
#define PIC_SSPSTAT_BIT_CKE 0x40
#define PIC_SSPSTAT_BIT_DA 0x20
#define PIC_SSPSTAT_BIT_P 0x10
#define PIC_SSPSTAT_BIT_S 0x08
#define PIC_SSPSTAT_BIT_RW 0x04
#define PIC_SSPSTAT_BIT_UA 0x02
#define PIC_SSPSTAT_BIT_BF 0x01
#define PIC_SSPCON1_BIT_WCOL 0x80
#define PIC_SSPCON1_BIT_SSPOV 0x40
#define PIC_SSPCON1_BIT_SSPEN 0x20
#define PIC_SSPCON1_BIT_CKP 0x10
#define PIC_SSPCON1_BIT_SSPM3 0x08
#define PIC_SSPCON1_BIT_SSPM2 0x04
#define PIC_SSPCON1_BIT_SSPM1 0x02
#define PIC_SSPCON1_BIT_SSPM0 0x01
#define PIC_SSPCON2_BIT_GCEN 0x80
#define PIC_SSPCON2_BIT_ACKSTAT 0x40
#define PIC_SSPCON2_BIT_ACKDT 0x20
#define PIC_SSPCON2_BIT_ACKEN 0x10
#define PIC_SSPCON2_BIT_RCEN 0x08
#define PIC_SSPCON2_BIT_PEN 0x04
#define PIC_SSPCON2_BIT_RSEN 0x02
#define PIC_SSPCON2_BIT_SEN 0x01
/* Byte Reg defines*/
#byte PIC_SSPBUF=0xFC9
#byte PIC_SSPADD=0xFC8
#byte PIC_SSPSTAT=0xFC7
#byte PIC_SSPCON1=0xFC6
#byte PIC_SSPCON2=0xFC5
#define RX_BUF_LEN 4
#define NODE_ADDR 0x04
unsigned char slave_buffer[RX_BUF_LEN];
unsigned char steering_string[RX_BUF_LEN];
int buffer_index;
int8 hallwheel = 0;
int8 hallwheelbuffer = 0;
int8 hallgear = 0;
int8 hallgearbuffer = 0;
signed int8 angle_out = 0;
int8 angle_car = 0;
int8 anglein = 0;
int16 anglein1 = 0;
int16 anglein2 = 0;
int16 anglein3 = 0;
#INT_SSP
void ssp_interupt ()
{
hand();
}
void hand()
{
unsigned char i2c_mask = 0x2D; /* 0010 1101 */
byte temp_sspstat;
unsigned char this_byte;
unsigned char tx_byte;
int x;
temp_sspstat = PIC_SSPSTAT & i2c_mask;
switch(temp_sspstat)
{
case 0x09:
for (x=0; x<RX_BUF_LEN; x++)
{
slave_buffer[x]=0x00;
}
buffer_index=0;
this_byte = read_i2c();
break;
case 0x29:
this_byte = read_i2c();
slave_buffer[buffer_index] = this_byte;
if (buffer_index == 2)
{
steering_control();
}
buffer_index++;
if (buffer_index >= RX_BUF_LEN)
{
buffer_index = 0;
}
break;
case 0x0c:
calculation_angle();
write_i2c(angle_out);
break;
case 0x2c:
break;
}
}
void steering_control()
{
strncpy (steering_string, slave_buffer, 4);
anglein3 = ((steering_string[0] - 0x30)*100);
anglein2 = ((steering_string[1] - 0x30)*10);
anglein1 = (steering_string[2] - 0x30);
anglein = anglein3 + anglein2 + anglein1;
set_pwm1_duty(anglein);
}
void calculation_angle()
{
angle_car = read_adc();
if(angle_car <= 42)
{
angle_out = 21;
}
if(angle_car >= 43 && angle_car <= 45)
{
angle_out = 14;
}
if(angle_car >= 46 && angle_car <= 48)
{
angle_out = 7;
}
if(angle_car >= 49 && angle_car <= 51)
{
angle_out = 0;
}
if(angle_car >= 52 && angle_car <= 54)
{
angle_out = -7;
}
if(angle_car >= 55 && angle_car <= 57)
{
angle_out = -14;
}
if(angle_car >= 58)
{
angle_out = -21;
}
}
void initialize(void)
{
set_tris_a(0b00000001);
set_tris_b(0b00000111);
set_tris_c(0b00011000);
PIC_SSPCON1 = 0x36;
PIC_SSPADD = NODE_ADDR;
PIC_SSPSTAT = 0x00;
setup_adc_ports(AN0_VREF_VREF);
setup_adc(ADC_CLOCK_INTERNAL);
setup_ccp1(CCP_PWM);
setup_port_a( ALL_ANALOG );
setup_timer_2(T2_DIV_BY_16,255,1);
set_adc_channel( 0 );
set_pwm1_duty(83);
enable_interrupts(INT_SSP);
}
unsigned char read_i2c(void)
{
return PIC_SSPBUF;
}
void write_i2c(unsigned char transmit_byte)
{
unsigned char write_collision = 1;
while (PIC_SSPSTAT & PIC_SSPSTAT_BIT_BF)
{
}
while (write_collision)
{
PIC_SSPCON1 &= ~PIC_SSPCON1_BIT_WCOL;
PIC_SSPBUF = transmit_byte;
if(PIC_SSPCON1 & PIC_SSPCON1_BIT_WCOL)
{
write_collision = 1;
}
else
{
write_collision = 0;
}
}
PIC_SSPCON1 |= PIC_SSPCON1_BIT_CKP;
}
void main()
{
output_high(PIN_B4);
delay_ms(200);
output_low(PIN_B4);
initialize();
enable_interrupts(GLOBAL);
while (1)
{
}
}
|
THANKS |
|
|
sd211
Joined: 15 Nov 2005 Posts: 4 Location: NC, USA
|
Re: 18F242 change from 3.278MHz to 20Mhz |
Posted: Fri Feb 17, 2006 2:40 pm |
|
|
The problem is most likely with the oscillator, not I2C. What caps do you have for crystal? 20MHz usually will work well with 20-22pF caps. If you have "blink-a-led" program, does PIC restart?
Sergey |
|
|
Grouchy Guest
|
|
Posted: Sat Feb 18, 2006 1:23 pm |
|
|
Hi!
What about the "#use i2c" directive?
What are the options that you're using on the MASTER?
try this:
#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3,FORCE_HW) |
|
|
iso9001
Joined: 02 Dec 2003 Posts: 262
|
|
Posted: Sat Feb 18, 2006 4:25 pm |
|
|
I don't have much to add to your post but it seems that the 18F2520 is cheaper then the 18F242. Thats in low quanities from mouser. Microchips site says the 2420 is a lot cheaper, but it looks like street price is better for the 2520
They look to me like the exact same chip except for the 2520 having twice the rom and twice the ram.
Not sure if you knew that or not, or if it helps. But anyway,
EDIT: nevermind, I was looking at the non-rohs version, the 2420 is cheaper. But not by much. |
|
|
PICLeo
Joined: 14 Dec 2005 Posts: 11 Location: South Africa
|
|
Posted: Mon Feb 20, 2006 12:58 am |
|
|
Hi
I use 22pF caps. So that should be allright. I also use exactly the options Grouchy mentioned.
Yesterday I also tried to get a very simple program started.
Its just like:
output_high(PIN_B4);
delay_ms(500);
output_low(PIN_B4);
If i switch the PIC on the LED sometimes glows for 3 seconds. Another time for maybe 1 second. It must be quite confused.
For the case I connect the oszi I still do not get a sinus-signal....
What else can there be wrong? |
|
|
sd211
Joined: 15 Nov 2005 Posts: 4 Location: NC, USA
|
|
Posted: Mon Feb 20, 2006 2:13 pm |
|
|
PICLeo wrote: | Hi
I use 22pF caps. So that should be allright. I also use exactly the options Grouchy mentioned.
Yesterday I also tried to get a very simple program started.
Its just like:
output_high(PIN_B4);
delay_ms(500);
output_low(PIN_B4);
If i switch the PIC on the LED sometimes glows for 3 seconds. Another time for maybe 1 second. It must be quite confused.
For the case I connect the oszi I still do not get a sinus-signal....
What else can there be wrong? |
Sounds like oscillator problem. Make sure you select HS option for the oscillator. I do not remember exact syntax and I am away from my compiler, so check docs.
If this opition is selected, verify that you get stable oscillation, use 1:10 settings on the oscilloscope probe, otherwise it will interfere with the oscillator.
Sergey |
|
|
|
|
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
|