|
|
View previous topic :: View next topic |
Author |
Message |
ssaakmnt
Joined: 03 Dec 2011 Posts: 27
|
rs232 character receiving |
Posted: Sat Dec 03, 2011 2:41 am |
|
|
hello every one i have no much experience with pic i try to send character (or int) with rs232 to break a while loop , the code is ok except the second while loop that i cant escape
#include <16F84.H>
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_a0, rcv=PIN_a1)
void main() {
while(1){
char c;
c=getc();
switch (c)
{
case '1':
output_high(pin_b0);
break;
case '4':
output_low(pin_b0);
break;
case '2':
output_high(pin_b1);
break;
case '5':
output_low(pin_b1);
break;
case '3':
output_high(pin_b2);
break;
case '6':
output_low(pin_b2);
break;
case '7':
while(!c == '4')
{output_high(pin_b0);
delay_ms(100);
output_low(pin_b0);
delay_ms(100);}
break;
}
} |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Sat Dec 03, 2011 3:37 am |
|
|
Think about it:
Code: |
case '7':
while(!c == '4') {
output_high(pin_b0);
delay_ms(100);
output_low(pin_b0);
delay_ms(100);
}
break;
}
|
You execute this code, if c=='7'. Now c therefore is _not_ going to be '4', so the while loop will execute. Inside the while loop, c never changes, so the loop _will_ execute for ever.
If (for instance), you wanted this to execute four times, you would need:
Code: |
case '7':
for (c=0;c<4;c++) {
output_high(pin_b0);
delay_ms(100);
output_low(pin_b0);
delay_ms(100);
}
break;
}
|
Also learn to use the code buttons, and indentation....
Now if you want the rs232 to 'break' the loop, you need to rethink big time. You are using software RS232. This implies that characters can't signal your code to do anything. Your code needs to _test_ for the characters all the time, and at 9600bps, if data is not going to be missed, the test needs to be at least 20000 times per second. Are you testing inside the delays?. No. Are you testing in the inner while loop?. No. So the characters will be missed.....
It is possible to program what you want, (I think, from your basic description), but involves much more work. A number of possibilities, and all involve more thinking. For example:
Code: |
int16 ctr;
c=0;
do {
output_high(PIN_B0);
for (ctr=0;ctr<1000;ctr++) {
delay_us(90);
if (kbhit()) {
c=getc();
break;
}
}
if (c!=0) break;
output_low(PIN_B0);
for (ctr=0;ctr<1000;ctr++) {
delay_us(90);
if (kbhit()) {
c=getc();
break;
}
}
} while (c==0);
//You get here if a RS232 character arrives, with the character in c
|
This is about the crudest way, without involving interrupts for either the flashing, or the RS232. You loop in a much faster delay loop (about 100uSec/loop with the increment and test), and if a character is seen (kbhit) fetch it, and exit.
Best Wishes |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Sat Dec 03, 2011 6:44 am |
|
|
Sooner or later and most often it is sooner most realize that in order to avoid the dropping of inbound characters an isr driven circular buffer is needed. I'd recommend searching this forum for examples. CCS has a good example of a circular buffer. Now of course this assumes you will use the hardware UART. Again most will use the hardware inside the PIC chip for RS232 since that's what it is there for. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sat Dec 03, 2011 8:13 am |
|
|
The PIC16F84(A) has no hardware UART. Receiving serial data is still possible because the CCS compiler will create a software based UART but this comes with limitations:
- No interrupts possible for received data
- Because no interrupts, no background reception of data.
- Data can only be received when getc() is active. This means you have to call kbhit at least ten times the bit rate.
Some people combined the CCS software UART with an interrupt on the RB0/INT pin, then most of the above mentioned limitations are gone. However, because of delays in interrupt handling this only works when your maximum baudrate is about 400 times smaller than your clockspeed. For example at 4MHz the maximum baudrate would be about 10kbaud. ~ 9600baud.
However, best solution in my opinion is to choose another chip with hardware UART. The PIC16F64 is very, very, old. Newer chips are cheaper, use less power and have more options. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Sat Dec 03, 2011 9:13 am |
|
|
I think you are slightly 'overstating' the speeds necessary.
You can use the INT_EXT triggering getc, up to about 1/120th your clock speed, rather than 1/400th your clock speed. You need to use the 'SAMPLE_EARLY' option. Then the getc, starts reading immediately when you arrive in the interrupt, instead of delaying by 1/2 a bit time, and given the typically 30 instruction times needed to get into an interrupt (120 clock cycles), this allows operation up to about 32Kbaud at 4MHz.
Similarly on how often you need to poll the pin, anything over twice, and preferably at least 3* per bit time is OK, not "ten times bit rate".
However agree wholeheartedly, the hardware UART, is simpler, better, just 1000* simpler, etc. etc...
Best Wishes |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sat Dec 03, 2011 9:35 am |
|
|
Quote: |
No interrupts possible for received data
|
sorry not precisely true -- ther are ways to use int and a defined communication protocol that i did almost 2 years ago , based on the hardware ISR method. i wrote a driver that utilizes the edge interrupt of
B port pins to create an ISR for non hardware rs-232 - and posted here
earlier this year.........
http://www.ccsinfo.com/forum/viewtopic.php?t=46369&highlight=
while i agree with the previous post that YES -
it still has the other liabilities of software rs-232 -
a lack of interrupt mediated reception is NOT One of them
if you use host_command --> pic_response protocols - this can work well enough. if data can arrive with really NO warning - then even this will fail you eventually.
|
|
|
ssaakmnt
Joined: 03 Dec 2011 Posts: 27
|
|
Posted: Sun Dec 04, 2011 5:29 am |
|
|
thank you for all your discussions guys there is a lot to think about .. and thank you Ttelmah for the code i will try it |
|
|
plainas
Joined: 22 Mar 2010 Posts: 4 Location: Portugal -> Aveiro
|
|
Posted: Wed Dec 07, 2011 5:59 pm |
|
|
hello I made a personal code that is tested, works as follows to send pic [sdfsdfsdvfgsd] know that the pic is shows the string and string. and is equal to an integer and a character.
eg to send the pic -> [c] / / character
-> [125] / / decimal integer 125
-> [Pedro] / / string "Peter"
I hope it is useful, this program is not good because the pic for the cycle.
Code: |
//***********************************************************
#include <16f877.h> // identifica microcontrolador alvo
#device ADC=10 // define AD para 10 bits, variando de 0 a 1023
#use delay (clock=4000000) // <- define cristal para 20Mhz. Para outros valores, mude e recompile.
#use RS232(baud=9600, xmit=PIN_C6,rcv=PIN_C7,STREAM = COM_1) // configura serial
// serial configurada para velocidade de 9600 bps
// sem paridade, 8 bits
#include <string.h>
#include <stdlib.h>
//******************************************************************************
//******************************************************************************
void compara_rx();
//******************************************************************************
//******************************************************************************
//******************************************************************************
// VALORES FINAIS DE RESULTADOS:
int n=0;
char valor[30];
char x='\0';
int1 f_inicio=0;
int1 f_fim=0;
int1 f_inteiro=0;
int1 f_caracter=0;
int1 f_string=0;
int resultado_int=0;
char resultado_char='\0';
char resultado_string[30];
//******************************************************************************
//******************************************************************************
//******************************************************************************
boolean f_100ms_0= 0;
boolean f_500ms_0= 0;
boolean f_1000ms_0= 0;
//*****************************************************************************
//*****************************************************************************
#int_timer0
void trata_t0(){ // FUNÇAO PARA CONTAGEM DE TEMPO DE 4 Ms
// static long int cont_rs232=0;
static long int cont_100=0;
static long int cont_500=0;
static long int cont_1000=0;
set_timer0(131 + get_timer0());
cont_100++;
cont_500++;
cont_1000++;
if(cont_100==25){//100ms
cont_100=0;
f_100ms_0=!f_100ms_0;
}
if(cont_500==125){//500ms
cont_500=0;
f_500ms_0=!f_500ms_0;
}
if(cont_1000==250){//1000ms
cont_1000=0;
f_1000ms_0=1;
}
}
//******************************************************************************
//***************************** RS232 ******************************************
//******************************************************************************
void recebe_dado_2(){
if(kbhit (COM_1)==0){
return;
}
x=getc();
valor[n]=x;
// putchar(x);
// INICIO:
if(x=='[' && !f_inicio){
f_inicio=1;
f_fim=0;
}
// FIM:
if(x==']' && f_inicio){
f_inicio=0;
f_fim=1;
}
//RECEBE UMA STRING E DEPOIS COMPARA:
if(f_inicio && ((x>=' ' && x<='Z') || (x>='a' && x<='z'))){
valor[n]=x;
n++;
}
if(f_fim){
f_fim=0;
valor[n]='\0';
x='\0';
//printf("\r\nSTRING ->%s",valor);
n=0;
f_string=0;
compara_rx();
}
}
//******************************************************************************
//***************************** RS232 ******************************************
//******************************************************************************
void compara_rx(){
int comp=0;
int n=0;
comp=strlen(valor);
f_inteiro=1;
f_caracter=1;
f_string=1;
//printf("\n\rCOMPRIMENTO DA STRING -> %u",comp);
for(n=0;n<comp;n++){
// NUMERO INTEIRO
if((valor[n]>='0' && valor[n]<='9') && n<3 && comp<=3){
}
else{
f_inteiro=0;
//printf("\n\r INTEIRO FALHOU!");
}
}
for(n=0;n<comp;n++){
// CHAR
if(((valor[n]>=' ' && valor[n]<='/') || (valor[n]>=':' && valor[n]<='Z') || (valor[n]>='a' && valor[n]<='z')) && n==0 && comp==1){
}
else{
f_caracter=0;
// printf("\n\r CARACTER FALHOU!");
}
// STRING
if(((valor[n]>=' ' && valor[n]<='Z') || (valor[n]>='a' && valor[n]<='z')) && comp>=2 && !f_inteiro){
//f_string=1;
}
else{
f_string=0;
//printf("\n\r STRING FALHOU!");
}
}
if(f_inteiro){
resultado_int=atoi(valor);
printf("\r\nO VALOR RECEBIDO FOI INTERIRO: -> %u",resultado_int);
}
if(f_caracter){
resultado_char=valor[0];
printf("\n\rO VALOR RECEBIDO FOI CARACTER: -> %c",resultado_char);
}
if(f_string){
strcpy(resultado_string,valor);
printf("\r\nO VALOR RECEBIDO FOI STRING: -> %s",resultado_string);
}
}
//******************************************************************************
//******************************************************************************
//**************************** MAIN ********************************************
//******************************************************************************
void main(){
setup_timer_0 ( RTCC_INTERNAL | RTCC_DIV_32 );
set_timer0(131);
enable_interrupts(global|int_timer0);
printf("\n\rLEIRURA DE PORTA COM!");
//******************************************************************************
//******************************************************************************
while(true){
if(f_100ms_0){
output_high(pin_b0);
}
else{
output_low(pin_b0);
}
recebe_dado_2();
if(f_inteiro){
f_inteiro=0;
printf("\r\nO VALOR RECEBIDO FOI INTERIRO: -> %u",resultado_int);
printf("\r\n -> %u",resultado_int);
}
if(f_caracter){
f_caracter=0;
printf("\n\rO VALOR RECEBIDO FOI CARACTER: -> %c",resultado_char);
printf("\n\r -> %c",resultado_char);
}
if(f_string){
f_string=0;
printf("\r\nO VALOR RECEBIDO FOI STRING: -> %s",resultado_string);
printf("\r\n-> %s",resultado_string);
}
}
} |
|
|
|
|
|
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
|