|
|
View previous topic :: View next topic |
Author |
Message |
Sigma
Joined: 03 May 2004 Posts: 48 Location: Sg
|
code migration from 16LF73 to 16LF76 |
Posted: Wed Nov 24, 2004 1:07 am |
|
|
Hi, All,
I have a piece of code to migrate from 16LF73 to 16LF76. Compiler version 3.148. The program is a software rs232 on pin_b0. (Later i try to post a sample code on the forum) The code is working fine on 16LF73, but after i modified #include <16F73.h> to #include <16F76.h> (i think that is the only change in the firmware. because these 2 chips are pin to pin compatible, and only that 16LF76 has a bigger size of program memory) The code does not work as good as run in 16LF73. Sometimes communication would break down.
Anybody familiar with these 2 chips? And know what makes this difference?
regards
Sigma |
|
|
Sigma
Joined: 03 May 2004 Posts: 48 Location: Sg
|
|
Posted: Wed Nov 24, 2004 2:32 am |
|
|
Here is the simplified version of the code:
Code: |
#include <16F76.h>
#fuses XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT
//----- Pin assignment ---------------------------------------------------------------------
#define PBUS PIN_B0 //PBus
#define RLED PIN_C0 //Red LED
#define GLED PIN_C1 //Green LED
//----- Command Table ----------------------------------------------------------------------
#define nCMD 15
#define SYNC 0xB5
#define C1 0xBA
#define C2 0xBB
#define C3 0xBC
#define YA 0xBD
#define ACK 0xBE
char len[nCMD]={0,0,1,2,3,
3,1,0,1,2,
2,4,1,0,0, //C1, C2, C3, YA, ACK
};
#define NORMAL 0
#byte INTCON = 0x0B
#bit INTF = INTCON.1
/*******************************************************************************************
* Variable Declaration
*******************************************************************************************/
short rxOK;
char buf[20];
char cmd;
char sleep_count;
char temp;
/*******************************************************************************************
* PBus - Using RS232 (Half duplex) functions
*******************************************************************************************/
#use delay(clock=4000000)
#use rs232(baud=9600, bits=8, xmit=PBUS, rcv=PBUS,float_high)
//------------------------------------------------------------------------------------------
short kbhit_pbus(void)
{
return kbhit();
}
char getPbusByte()
{
char r=0;
long i=0;
char j=0;
while(i<100){
if(kbhit_pbus()){
r=getc();
break;
}
else{
[b]//delay_us(1);[/b]
[b]i++;[/b]
}
}
return r;
}
//------------------------------------------------------------------------------------------
void pbus_send(char cmd)
{
char c;
char i;
char temp;
temp=cmd-0xB0;
putc(SYNC);
delay_us(10);
putc(cmd);
if (len[temp]>0) {
for(i=0;i<len[temp];i++) {
delay_us(10);
putc(buf[i]);
}
}
}
//------------------------------------------------------------------------------------------
void pbus_receive() {
char rx,i;
char temp;
[color=red]rxOK=FALSE;[/color]
if(getPbusByte()==SYNC){
cmd = getPbusByte();
temp = cmd-0xB0;
if (len[temp]!=0) {
for (i=0; i<len[temp]; i++) {
buf[i]=getPbusByte();
}
rxOk=TRUE;
}
else rxOK=TRUE;
}
}
/*******************************************************************************************
* General Functions
*******************************************************************************************/
void blinkRLED(char c)
{
char i;
for (i=0; i<c; i++) {
output_high(RLED);
delay_ms(10);
output_low(RLED);
if (i<(c-1))delay_ms(50);
}
}
//------------------------------------------------------------------------------------------
void blinkGLED(char c)
{
char i;
for (i=0; i<c; i++) {
output_high(GLED);
delay_ms(10);
output_low(GLED);
if (i<(c-1))delay_ms(50);
}
}
/*******************************************************************************************
* main
*******************************************************************************************/
main() {
short done;
char count_to_sleep;
char state;
port_b_pullups(TRUE); //Port B weak pullup
output_low(GLED); //Off the green LED
output_low(RLED); //Off the red LED
ext_int_edge(h_to_l); //External interrupt edge from high to low
enable_interrupts(INT_EXT); //PBUS is interrupt to wakeup
disable_interrupts(GLOBAL); //Don't use interrupt
done=FALSE;
count_to_sleep=4;
INTF=0;
blinkGLED(5);
while (1) {
port_b_pullups(TRUE); //Port B weak pullup
if(INTF){ //If external interrupt (PIN_B0) flagged
while(sleep_count<count_to_sleep){
[b]pbus_receive();[/b]
if(rxOK){
sleep_count=0;
state=cmd;
}
switch (state){
case NORMAL:
break;
case YA:
pbus_send(C1);
break;
case C2:
pbus_send(C3);
break;
case ACK:
blinkGLED(5);
state=NORMAL;
break;
}
sleep_count++;
}
} //end if(INTF)
sleep_count=0; //Reset count before sleep
count_to_sleep=4; //Reset count_to_sleep to 4
port_b_pullups(FALSE); //Port B weak pullup
output_low(RLED); //Off red LED
output_low(GLED); //Off green LED
INTF=0; //Clear EXT interrupt flag before sleep
done=FALSE;
state=NORMAL;
input(PBUS);
sleep(); //MCU sleep to save power
#asm
NOP //After wake-up, this is executed
#endasm
} //end while
}
/******************************************************************************************/
|
Thanks.
Sigma
Last edited by Sigma on Wed Nov 24, 2004 3:57 am; edited 2 times in total |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Wed Nov 24, 2004 3:04 am |
|
|
Quote: | #use rs232(baud=9600, bits=8, xmit=PBUS, rcv=PBUS,errors,float_high) |
rxOK is a global variable that is tested in the main() but is never initialised.
The "errors" and "float_high" are mutually exclusive. errors works only with the hardware uart and float high works only with the software uart.
Have you simplified the code too much? In getPBusByte variable i never changes so the delay_us() is never executed.
You have used delays in the switch statements. If the sw uart is used you may miss characters depending on how the application communicating to the PIC behaves. Similarly if the hw uart is used you may get an additional two characters before an overrun occurs.
I can see two ways of significantly impriving the code. One method is to select the HW UART and use interrupt driven receive logic. This will prevent characters being lost during delay_xx()
Alternatively move the LED flashing to a timer interrupt handler. Setup a periodic interrupt (say every 5ms) and use counters to control the LEDs. For example...
Code: |
// ..inside the timer interrupt handler
if (Redcount)
{
Redcount--;
output_high(RLED);
}
else
output_low(RLED);
if (Greencount)
{
Greencount--;
output_high(GLED);
}
else
output_low(GLED);
//......... |
To have the RED LED turn on for 50ms then in the mainline set Redcount = 10 _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Sigma
Joined: 03 May 2004 Posts: 48 Location: Sg
|
|
Posted: Wed Nov 24, 2004 3:54 am |
|
|
Thanks, Andrew. And i am really sorry i simplified the code too much. I already modified the code. Thanks.
Because i call pbus_receive(); in the main function, rxOK will be re-init again. 'i' is also increased when kbhit() not true until certain count exceeds.
I understand external interrupt can do the job, but using this polling i also achieved 0 error rate using 16LF73. But when the code exported to 76, it malfunctions. Their hardware properties should be quite the same, why there is such a difference? What do you think?
Sigma |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Wed Nov 24, 2004 4:30 am |
|
|
Is the hardware identical - that is the only thing that has changed is the PIC? What is the float_high used for? _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
|
|
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
|