CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

kbhit problem on software uart

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
doguhanpala



Joined: 05 Oct 2016
Posts: 120

View user's profile Send private message

kbhit problem on software uart
PostPosted: Fri Jan 18, 2019 6:41 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Fri Jan 18, 2019 7:23 am     Reply with quote

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: 9102
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jan 18, 2019 10:38 am     Reply with quote

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: 19219

View user's profile Send private message

PostPosted: Fri Jan 18, 2019 10:43 am     Reply with quote

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: 9102
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Jan 27, 2019 3:15 pm     Reply with quote

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: 19219

View user's profile Send private message

PostPosted: Mon Jan 28, 2019 1:59 am     Reply with quote

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. Very Happy
temtronic



Joined: 01 Jul 2010
Posts: 9102
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Jan 28, 2019 5:51 am     Reply with quote

sigh.... Sad
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: 19219

View user's profile Send private message

PostPosted: Mon Jan 28, 2019 7:39 am     Reply with quote

Unfortunately, there is a lot that is undocumented... Sad
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

View user's profile Send private message

PostPosted: Thu Jan 31, 2019 6:50 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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