|
|
View previous topic :: View next topic |
Author |
Message |
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
kbhit problem on software uart |
Posted: Fri Jan 18, 2019 6:41 am |
|
|
Hello everyone,
I have problem on my kbhit code.
I have an 18f4550 as master and 16f628 as slave. I use 1 port for rs232. 18f sends the data, 16f does the command and sends a voltage as the task is finished. It is a requirement for project to use 1 pin. Also i use software uart because when i use hardware uart the voltage code does not work.
I am trying to stop the slave code when it blinks led. You can see in rcv code, the led blinks for times. I am trying to interrupt it and stop the code in (for example) second blink.
Here is my transmitter code. It makes a synchronization for 1 time (sends a char waits for voltage). After that it sends a 7 byte message and waits for voltage again. Lastly, it sends another 7 byte message. This time it does not wait for voltage but sends another message to stop led blinking.
Code: |
#include <18F4550.h>
#DEVICE ADC=10
#fuses INTRC_IO,NOWDT,MCLR,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,CPUDIV1,VREGEN
#use delay(clock=8000000)
#use rs232(baud=9600, UART1, ERRORS,stream = bt)
#use rs232(baud=9600, xmit=PIN_B2,stream = motormodul)
#include <stdlib.h>
#include <string.h>
void main()
{
delay_ms(500);
output_high(PIN_D5); //mavi yan
putc(100,motormodul);
while(input_state(PIN_B2)!=0)
delay_us(100);
break; //high gelene kadar bekle
// end sync
delay_ms(10);
output_low(PIN_D5); //mavi sön
output_high(PIN_D6); //kırmızı yan
putc(254,motormodul);
putc(35,motormodul);
putc(5,motormodul);
putc(4,motormodul);
putc(5,motormodul);
putc(0,motormodul);
putc(255,motormodul);
while(input_state(PIN_B2)!=0)
delay_us(100);
break;
output_low(PIN_D6); //kırmızı sön
delay_ms(1000);
output_high(PIN_D5); //ikisi de yan
output_high(PIN_D6);
putc(254,motormodul);
putc(35,motormodul);
putc(5,motormodul);
putc(5,motormodul);
putc(0,motormodul);
putc(1,motormodul);
putc(255,motormodul);
delay_ms(500);
putc(100,motormodul);
putc(100,motormodul);
putc(100,motormodul);
output_low(PIN_D5); // ikisi de sön
output_low(PIN_D6);
}
|
Here is the rcv code. I am trying to understand that the 3rd kbhit function(in for loop) never works. Any ideas?
Code: |
#include <16F628.h>
#DEVICE ADC=10
#fuses INTRC_IO,NOWDT,NOMCLR,NOPROTECT,NOLVP,NOBROWNOUT
#use delay(clock=4000000)
#use rs232(baud=9600, rcv=PIN_B1)
#include <stdlib.h>
#include <string.h>
#define START_BYTE 254
#define STOP_BYTE 255
int8 data[7]= {0,0,0,0,0,0,0};
int msj_ok;
int bos;
int1 flag=0;
void handle_comm();
void sync();
void bitir();
void ledyak();
int16 step_sayisi = 0;
int16 sayac=0;
void main()
{
delay_ms(100);
while(1)
{
msj_ok = 0;
if(kbhit() && flag == 0) sync(); // this works
if(kbhit()) handle_comm(); // this works too. the message comes succesfully
if(msj_ok)
{
int a=0;
for(a=0;a<10;a++)
{
if(kbhit()) bos=getc(); // this line never works. even though i send another char during the code, kbhit does not seem to be working.
}
ledyak(); //led blinks 4 times
bitir(); // this sends the voltage
}
}
}
void sync()
{
bos= getc();
delay_ms(500);
bitir();
flag=1;
}
void handle_comm()
{
int k;
for(k=0;k<7;k++)
{
data[k]=getc();
if(data[0]!=START_BYTE)
{
bitir();
break;
}
if(data[6]==STOP_BYTE)
{
msj_ok=1;
}
}
}
void bitir()
{
output_high(PIN_B1);
delay_ms(2);
output_low(PIN_B1);
delay_ms(2);
}
void ledyak()
{
int a=0;
for(a=0;a<4;a++)
{
output_high(PIN_B5);
delay_ms(500);
output_low(PIN_B5);
delay_ms(500);
}
}
|
Thank you very much!
My best wishes,
Doguhan |
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Fri Jan 18, 2019 7:23 am |
|
|
In the ccs compiler manual it says that if you use software uart then you should be polling kbhit() at about ten times the baud rate to avoid missing any incoming messages.
In some old code I had, if I had too many delays that's what would happen. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Fri Jan 18, 2019 10:38 am |
|
|
OK your 628 PIC is using the HW UART(pin B1), so you need to add 'ERRORS' tot eh #USE RS232(...options...).
What's probably happening is that the HW UART is 'locked' ( framing error) as 3 characters have been sent from the master and you (628) haven't read them OUT of the HW UART 'buffer'.
Normally you need to 'clear' the serial input buffer BEFORE enabling or allowing or looking for incoming data. When a PIC powers up ,there can be garbage data in the UART .
Usually with serial reception you use an ISR and a buffer. EX_SISR.C is an
example program CCS supplies. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Fri Jan 18, 2019 10:43 am |
|
|
You have to understand that the software UART, is totally software. No
buffering, no capability for data to be arriving and stored. You have to
actually be reading the incoming character significantly before you get
even half way into a bit, or that bit will be missed.
Kbhit, simply tests for the line going low, and so unless it is called often
enough to ensure that you will detect this and can call the getc, well
before half way through the character, data will be lost.
Your bit_ir call once the start byte is seen, ensures you _will_ be missing
subsequent characters.... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Sun Jan 27, 2019 3:15 pm |
|
|
been thinking about this pos for awhile, cause something didn't seem right...
this...
putc(254,motormodul);
isn't legit, should be
fput(254, motomodul);
from the manual....
fputc(cdata, stream) |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Mon Jan 28, 2019 1:59 am |
|
|
That's an 'undocumented' extension.
On the last few compiler releases, CCS have 'overloaded' the putc implementation. so if you use:
putc(val, STREAM)
it merrily calls fputc.
I agree one should really stick with the documented usage, but knew that this
wasn't an issue, so didn't raise it. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Mon Jan 28, 2019 5:51 am |
|
|
sigh....
makes me wonder what else is undocumented yet works....
I should have tweaked on 'no errors-it compiles'
I wonder if anyone has documented the undocumented ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Mon Jan 28, 2019 7:39 am |
|
|
Unfortunately, there is a lot that is undocumented...
Things like the keywords supported by getenv for example, and some of the
micro syntax of many commands, which either requires you to look through
the compiler's DLL's., or search here.
Historically when the compiler was 'young', the manual was very good. Sadly
many of the more recently added functions, have the manual 'lagging' the
actual compiler. So keywords for some things like DMA lag massively,
and are not in the header file either.
Keeping up to date with what 'works', is almost a full time occupation... |
|
|
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
|
Posted: Thu Jan 31, 2019 6:50 am |
|
|
temtronic wrote: | OK your 628 PIC is using the HW UART(pin B1), so you need to add 'ERRORS' tot eh #USE RS232(...options...).
What's probably happening is that the HW UART is 'locked' ( framing error) as 3 characters have been sent from the master and you (628) haven't read them OUT of the HW UART 'buffer'.
Normally you need to 'clear' the serial input buffer BEFORE enabling or allowing or looking for incoming data. When a PIC powers up ,there can be garbage data in the UART .
Usually with serial reception you use an ISR and a buffer. EX_SISR.C is an
example program CCS supplies. |
Dear temtronic and Ttelmah
Thank you for your answer and i am sorry for late reply.
I tried to use the hardware uart. But that way i could not understand if the stepper motor finished or not. Because the input state gets to low before the command is finished.
As the project requires i cannot use 2 pins for receive and transmitting. So that high and low voltage was my solution to understand if the command was finished or not.
As for Ttelmah's reply
Ttelmah wrote: | Kbhit, simply tests for the line going low, and so unless it is called often
enough to ensure that you will detect this and can call the getc, well
before half way through the character, data will be lost.
Your bit_ir call once the start byte is seen, ensures you _will_ be missing
subsequent characters.... |
This version of my code works successfully. I tried multiple times. So i thought the problem is not on the "bitir" function. I believe Ttelmah is right and the reason this works is in another part of the code but i don't know where.
Code: |
#include <16F628.h>
#DEVICE ADC=10
#fuses INTRC_IO,NOWDT,NOMCLR,NOPROTECT,NOLVP,NOBROWNOUT
#use delay(clock=4000000)
#use rs232(baud=9600, rcv=PIN_B1)
#define motor1_pin1 PIN_A0
#define motor1_pin2 PIN_A1
#define motor1_pin3 PIN_A2
#define motor1_pin4 PIN_A3
#define motor2_pin1 PIN_B7
#define motor2_pin2 PIN_B6
#define motor2_pin3 PIN_B5
#define motor2_pin4 PIN_B4
#define START_BYTE 254
#define STOP_BYTE 255
int8 data[7]= {0,0,0,0,0,0,0};
int msj_ok;
int bos;
int1 flag=0;
void handle_comm();
void motor1_s1();
void motor1_s2();
void motor1_s3();
void motor1_s4();
void motor1_s5();
void motor1_s6();
void motor1_s7();
void motor1_s8();
void motor2_s1();
void motor2_s2();
void motor2_s3();
void motor2_s4();
void motor2_s5();
void motor2_s6();
void motor2_s7();
void motor2_s8();
void robot_ileri();
void robot_geri();
void robot_sol();
void robot_sag();
void motor1_ileri();
void motor1_geri();
void motor2_ileri();
void motor2_geri();
void durdur();
void bitir();
void komutisle();
int16 step_sayisi = 0;
int16 sayac=0;
void sync()
{
bos= getc();
bitir();
flag=1;
}
void handle_comm()
{
int k;
for(k=0;k<7;k++)
{
data[k]=getc();
if(data[0]!=START_BYTE)
{
bitir();
break;
}
if(data[6]==STOP_BYTE)
{
msj_ok=1;
}
}
}
void bitir()
{
output_high(PIN_B1);
delay_ms(2);
output_low(PIN_B1);
delay_ms(2);
}
void komutisle()
{
step_sayisi = make16(data[5],data[4]); // step sayisi low ve high bytelar
switch(data[3])
{
case 1:
robot_ileri();
durdur();
bitir();
break;
case 2:
robot_sag();
durdur();
bitir();
break;
case 3:
robot_sol();
durdur();
bitir();
break;
case 4:
robot_geri();
durdur();
bitir();
break;
case 5:
motor1_ileri();
durdur();
bitir();
break;
case 6:
motor2_ileri();
durdur();
bitir();
break;
case 7:
motor1_geri();
durdur();
bitir();
break;
case 8:
motor2_geri();
durdur();
bitir();
break;
}
}
//................motor functions
void main()
{
delay_ms(100);
durdur();
while(1)
{
msj_ok = 0;
if(kbhit() && flag == 0) sync();
if(kbhit()) handle_comm();
//!
if (msj_ok)
{
msj_ok = 0;
komutisle();
}
else
bitir();
}
}
|
This code waits for message. When 16f gets the message it drives the motor and waits for another message. It gets it succesfully and drives the motor correctly. |
|
|
|
|
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
|