|
|
View previous topic :: View next topic |
Author |
Message |
ericchee
Joined: 03 Dec 2008 Posts: 12
|
Why working serial data not working on bluetooth module? |
Posted: Tue May 12, 2009 6:32 am |
|
|
Hi,
I have done serial sending and receiving using usb-serial port cable and it's working. Here is the code
Code: |
#include <16F877A.h>
#include <string.h>
#use delay(clock=20000000)
#fuses hs, noprotect, nowdt,nolvp
#byte PORTB=6
#byte PORTC=7
#define door PIN_B2
#define window PIN_B1
#define bumper PIN_B3
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define ChannelA PIN_A0
#define ChannelB PIN_A1
#define REDLED PIN_B4
#define GREENLED PIN_B6
#define YELLOWLED PIN_B3
#define DIRECTION PIN_D7
#include <input.c>
#include <stdlib.h>
#define STRING_SIZE 40
#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
#define bkbhit (next_in!=next_out)
char cmd_str[20];
long t0 = 0;
long t1 = 1;
byte bgetc()
{
byte c;
while(!bkbhit) ;
c=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
void get_cmd_str(char * s, int max) {
int len;
char c;
max--;
len = 0;
do {
c = bgetc();
if(c > 0x00) {
if(len < max) {
s[len++] = c;
}
}
}
while(bkbhit);
s[len]= 0x00;
}
#int_rda
void serial_received()
{
int t;
buffer[next_in]=getc();
t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out)
next_in=t; // Buffer full !!
}
#int_ext
void interrupt()
{
BYTE time3;
set_tris_b(0b00000001);
output_high(bumper);
time3 = get_timer0();
time3 += -1;
set_timer0(time3);
}
#int_rtcc
void timer0_isr()
{
t0 += 1;
}
#int_timer1
void timer1_isr()
{
t1 += 1;
set_timer1(0xFF00);
}
void main()
{
int PwM;
set_tris_b(0b00110001);
portb=0;
set_tris_d(0b00000001);
portb=0;
output_low(GREENLED);
output_low(REDLED);
output_low(YELLOWLED);
setup_timer_2(T2_DIV_BY_16, 127, 1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(0);
setup_counters( RTCC_EXT_H_TO_L, RTCC_DIV_1 );
set_rtcc(0);
setup_timer_1 ( T1_EXTERNAL | T1_DIV_BY_1 );
set_timer1(0xFFF4);
enable_interrupts(INT_RTCC);
enable_interrupts(INT_TIMER1);
EXT_INT_EDGE(L_TO_H);
ENABLE_INTERRUPTS(INT_EXT);
ENABLE_INTERRUPTS(INT_RDA);
enable_interrupts(GLOBAL);
main_program:
do
{
printf("%2x",t0);
printf("%2x",get_rtcc());
printf("%2x",t1);
printf("%2x\n\r",get_timer1());
output_high(GREENLED);
output_low(REDLED);
output_low(YELLOWLED);
if(bkbhit)
{
delay_ms(15); //Delay allows full string to arrive
get_cmd_str(cmd_str, 10);
}
PwM=atoi(cmd_str);
if(PwM >= 129)
{
PwM -= 129;
set_pwm1_duty(PwM);
output_high(DIRECTION);
}
else if(PwM <= 128)
{
set_pwm1_duty(PwM);
output_low(DIRECTION);
}
}while(TRUE);
goto main_program;
again:
output_low(GREENLED);
output_high(REDLED);
output_low(YELLOWLED);
goto again;
}
|
Then I implement this code to bluetooth but it is not working so i took reference from a sample from mplab picc.
Code: |
#include <16f877a.h>
__CONFIG(0x3F32);
#define seg PORTD // define 7 segment as PORTD
unsigned char a;
void init(void) // subroutine to initialize
{
SPBRG=0x0A; // set baud rate as 115200 baud
BRGH=1;
TXEN=1;
CREN=1;
SPEN=1;
TRISD = 0b00000000;
seg = 0b00000000;
}
void display(unsigned char c) // subrountine to display the text on the screen
{
while (TXIF == 0);
TXREG = c;
}
unsigned char receive(void) // subrountine to receive text from PC
{
while (RCIF == 0);
a = RCREG;
return a;
}
void main(void)
{
init();
while(1) // wait for 'ok' to be entered
{
a = receive();
if (a == 'o')
{
a = receive();
if (a == 'k') break;
}
}
display('C'); // change the text for different display
display('y');
display('t');
display('r');
display('o');
display('n');
display(0x0a);
display(0x0d);
display('P');
display('r');
display('e');
display('s');
display('s');
display(0x20);
display('a');
display('n');
display('y');
display(0x20);
display('n');
display('u');
display('m');
display('b');
display('e');
display('r');
seg = 1;
while(1) // wait for number and display it on 7 segment
{
a = receive();
if (a=='1'||a=='2'||a=='3'||a=='4'||a=='5'||a=='6'||a=='7'||a=='8'||a=='9'||a=='0')
{
seg = a-0x30;
}
}
}
|
and i modify my ccs picc to this
Code: |
#include <16F877A.h>
#device ADC=8
#use delay(clock=20000000)
#fuses hs, nowdt,nolvp, nowrt, noput
#use rs232(STREAM=serial, baud=115200, xmit=PIN_C6, rcv=PIN_C7,PARITY=N,BITS=8)
#define REDLED PIN_B4
#define GREENLED PIN_B6
#define YELLOWLED PIN_B3
#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
#define bkbhit (next_in!=next_out)
char cmd_str[20];
long t0 = 0;
long t1 = 1;
byte bgetc()
{
byte c;
while(!bkbhit) ;
c=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
void get_cmd_str(char * s, int max) {
int len;
char c;
max--;
len = 0;
do {
c = bgetc();
if(c > 0x00) {
if(len < max) {
s[len++] = c;
}
}
}
while(bkbhit);
s[len]= 0x00;
}
#int_rda
void serial_received()
{
}
void main()
{
float temp;
int temp1,temp2;
char ans;
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
set_tris_a(0b11111111);
output_low(GREENLED);
output_high(REDLED);
output_low(YELLOWLED);
setup_port_a(ANALOG_RA3_RA2_REF);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
delay_us(120000);
//while(1) // wait for 'o' to be entered
//{
//if(bkbhit)
//{
//delay_ms(15); //Delay allows full string to arrive
//get_cmd_str(cmd_str, 10);
//}
//if (cmd_str == 'o') break;
//ans=getc();
//if (ans == 'o') break;
//}
//printf("ready\n\r");
main_program:
do
{
output_high(GREENLED);
output_low(REDLED);
output_low(YELLOWLED);
temp = read_adc();
temp1 = temp * 150 / 255;
temp2 = (temp * 1500 / 255) - (temp1 * 10);
printf("Temperature: %d.%d degree\n\r",temp1,temp2);
delay_ms(2000);
}while(TRUE);
goto main_program;
again:
output_low(GREENLED);
output_high(REDLED);
output_low(YELLOWLED);
goto again;
}
|
this code works as well because i removed the 'wait for 'o' to be pressed' code. but when i try to use the use the code i turned off in the middle, the process wont starts. When i press 'o' then program starts working. Using sample code, when i press 'ok', the process starts. Any idea how to solve this. Thanks for your attention to such a long post.
Rdgs,
ericchee |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue May 12, 2009 4:12 pm |
|
|
If I understand your long question correctly you want know why the code below does not continue when you send "ok". Is this correct? Code: | while(1) // wait for 'o' to be entered
{
if(bkbhit)
{
delay_ms(15); //Delay allows full string to arrive
[code]get_cmd_str(cmd_str, 10);[/code]
}
if (cmd_str == 'o') break;
ans=getc();
if (ans == 'o') break;
}
printf("ready\n\r");
|
Code: | delay_ms(15); //Delay allows full string to arrive
| This is tricky. You assume that 15ms is long enough to receive the string. At the full 115200 baud this is enough time to receive 11 characters, but sometimes the Windows PC or Bluetooth chipset can add long delays.
It is also a waste of time when the data is received faster than the 15ms.
Code: | get_cmd_str(cmd_str, 10); | This function is difficult to use as it can stop on three conditions:
1) Reading a 0x00 character
2) After 10 characters read
3) When no more data is waiting to be processed.
So, when it returns you never know why. Was data received? How much? Was the string complete?
Why not use the code from the given example and modify it for CCS? Code: | // wait for 'ok' to be entered
while(1)
{
a = bgetc(); // bgetc will wait until a character is received
if (a == 'o')
{
a = bgetc();
if (a == 'k') break;
}
}
|
A few remarks: Code: | goto main_program;
again:
output_low(GREENLED);
output_high(REDLED);
output_low(YELLOWLED);
goto again; | Using goto in a C-program is considered poor programming skills. A do-while or other loop-construct results in easier to read code.
Besides, the above code is never executed as your while(TRUE) loop never exits. |
|
|
ericchee
Joined: 03 Dec 2008 Posts: 12
|
|
Posted: Tue May 12, 2009 7:53 pm |
|
|
Yes, you are correct.
Code: |
goto main_program;
again:
output_low(GREENLED);
output_high(REDLED);
output_low(YELLOWLED);
goto again; |
I never intend to use it anyway. All color LED is just for indication on which parts of the code is executing. And i know the code wouldn't exit because of the TRUE in while loop. I just prepare this in case any incident happen. Anyway, thanks for your remark. I'll avoid goto in future.
how exactly does this works? I just take from the sample and use it without really understand how it works. There should be mo termination condition just like
Am I right? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu May 14, 2009 6:23 am |
|
|
This is reading the data from the hardware UART directly. When no new data is available it will return the last received value, that is, this code will always return directly and not stop waiting for a new value.
This is similar to the above code, but it will wait for new data to arrive. That's why it is called a 'blocking' call.
Additionally, if you have the ERRORS directive in the '#use rs232' line this function will also clear the UART's error flags preventing the UART from stalling on a receive buffer overrun.
The getc function has a limitation:
- The hardware UART can only buffer up to 3 received characters, if you are late reading you will miss data.
bgetc is identical to getc but uses the receive interrupt to create a large receive buffer.
if you combine bgetc with bkbhit, you can create a program that has time to perform other actions while in the background data is received. For example the program below will toggle a led every 500ms while data is received in the background.
Code: | #define LED PIN_B1
while(TRUE)
output_toggle(LED);
delay_ms(500);
if (bkbhit()) // Is data received?
{
a = bgetc(); // read data
putc(a); // echo received data to PC
}
}
|
|
|
|
ericchee
Joined: 03 Dec 2008 Posts: 12
|
|
Posted: Wed May 20, 2009 6:15 am |
|
|
Good explanation ckielstra.
Now i understand the detailed operation of the code. Too bad I can't test the solution you suggested to me. The bluetooth module no longer with me. Anyway, thank you for knowledge sharing. |
|
|
|
|
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
|