View previous topic :: View next topic |
Author |
Message |
ivojk
Joined: 20 Jun 2010 Posts: 6
|
How to make line Break UART |
Posted: Sun Jun 20, 2010 8:11 am |
|
|
Hi,
I need set break state on UART TX line for a different time.
I'm using 18F2550
I try to disable transceiver but don't work.
Can somebody help me with source how to make line break or with library for software UART with break function.
I'm using CCS C compiler
BR |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 20, 2010 11:13 am |
|
|
Quote: |
I need set break state on UART TX line for a different time.
I'm using 18F2550
|
Look in the 18F2550 data sheet. It has an EUSART module, which has
the ability to send a Break. CCS has support for this, with the following
line of code:
Code: |
setup_uart(UART_SEND_BREAK);
|
|
|
|
ivojk
Joined: 20 Jun 2010 Posts: 6
|
re: |
Posted: Sun Jun 20, 2010 11:47 am |
|
|
Hi,
I know this but this break send only 12 bits.
I need to make a break for a more long time.
I need to set line in break for 20ms for 30ms and etc.
I need to tell how long to be line in break state.
BR |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 20, 2010 1:38 pm |
|
|
Try this routine. It should work.
Code: |
#include <18F452.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#define BAUDRATE 9600
#define TX_PIN PIN_C6
#define RX_PIN PIN_C7
#use rs232(baud=BAUDRATE, xmit=TX_PIN, rcv=RX_PIN, ERRORS)
void send_break(int8 time_ms)
{
// Disable the UART and send a Break
// for the specified time.
setup_uart(FALSE);
output_low(TX_PIN);
delay_ms(time_ms);
// Re-enable the UART.
setup_uart(TRUE);
set_uart_speed(BAUDRATE);
}
//======================================
void main(void)
{
int8 i;
while(1)
{
// Send 10 bytes of 0x55 to show UART activity
for(i=0; i<10; i++)
putc(0x55);
send_break(20);
}
}
|
Also, what's your compiler version ? I think there is a problem with the
delay_ms() routines for the 18F4550 and 18F2550. For versions 4.100
to 4.107, they run 4x longer than they should. For example, a 1 ms
delay becomes 4 ms. I tested this in hardware. (I couldn't test
vs. 4.108 yet, because I need to get a new .CRG file from CCS before
I can run it). This problem may only affect the 18F4550-series of PICs,
because I tested vs. 4.107 with an 18F452, and delay_ms() works
correctly. When I get the new .CRG files from CCS, I'll test vs. 4.108.
If it fails, then I'll email CCS support about it. |
|
|
ivojk
Joined: 20 Jun 2010 Posts: 6
|
re: |
Posted: Sun Jun 20, 2010 3:01 pm |
|
|
Hi,
I'm using V4.107
For me delay_ms() work correct with this version.
With setup_uart() break work but I see other problem
I can't receive after this.
BR |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sun Jun 20, 2010 3:15 pm |
|
|
I'd probably just disable the transmit part, and do direct I/O, rather than using the CCS functions. It may be that the latter get confused after the changes.
So something like:
Code: |
#byte TXSTA=0xFAC
#bit TXEN=TXSTA.5
#byte C_LAT=0xF8B
#bit TXBIT=C_LAT.6
void send_break(int8 msec) {
C_LAT=0; //ensure latch is low, before disabling UART TX
TXSTA=0;
delay_ms(msec);
TXSTA=1;
}
|
This way the receive side of the UART remains enabled.
On the software UART, you can just output a low, delay, then set the line high, wait one bit time, and carry on using the software UART functions as normal (you must set it back 'high', or the start bit for the next character will be missed.
Best Wishes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 20, 2010 3:15 pm |
|
|
It works for me. I compiled the following program with vs. 4.107 and
it gives this output:
Quote: |
Start:asdfasdfasdfasdf
|
I typed asdf repeatedly, and it sends the characters to the PIC from
the terminal window on the PC, and the PIC sends them back to the PC.
It's working.
I did find the problem with the delay_ms() routine is actually a problem
with the default fuse settings in vs. 4.100 to 4.107 (and possibly later).
The compiler is using CPUDIV4 as the default. You can fix it by adding
CPUDIV1 to the list of #fuses as shown below:
Code: |
#include <18F4550.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP, CPUDIV1
#use delay(clock=4000000)
#define BAUDRATE 9600
#define TX_PIN PIN_C6
#define RX_PIN PIN_C7
#use rs232(baud=BAUDRATE, xmit=TX_PIN, rcv=RX_PIN, ERRORS)
void send_break(int8 time_ms)
{
// Disable the UART and send a Break
// for the specified time.
setup_uart(FALSE);
output_low(TX_PIN);
delay_ms(time_ms);
// Re-enable the UART.
setup_uart(TRUE);
set_uart_speed(BAUDRATE);
}
//======================================
void main(void)
{
int8 c;
printf("Start:\n\r");
send_break(20);
while(1)
{
c = getc(); // Get a char from the PC
putc(c); // Send it back to the PC
}
} |
|
|
|
ivojk
Joined: 20 Jun 2010 Posts: 6
|
RE |
Posted: Mon Jun 21, 2010 12:12 am |
|
|
Hi,
PCM programmer - can you try to receive with PIC after break? Sending work perfect but on me I can't receive.
Ttelmah - I will try later your code and write result.
BR |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Mon Jun 21, 2010 1:54 am |
|
|
Have you got 'errors' in your RS232 setup?. Are you receiving using an interrupt, or just waiting for characters?.
Problem is, what is going to happen while you are sending the 'break'.
'Errors', should always be used on the hardware UART, unless you are manually handling the error bits yourself. Should really be the 'default'.
My code will allow an interrupt driven receive to carry on working (only turns off the transmit component in the UART).
Best Wishes |
|
|
ivojk
Joined: 20 Jun 2010 Posts: 6
|
re |
Posted: Mon Jun 21, 2010 3:36 am |
|
|
Hi,
This is a part of my code about reading from UART
void read(void)
{
char Counter, i;
Counter = getc();
for (i=1; i < Counter; i++)
{
Buffer[i] = getc();
}
}
I don't use interupts. I call getc() and wait to receive.
BR |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Mon Jun 21, 2010 3:56 am |
|
|
You absolututely _must_ have ERRORS in your RS232 declaration then. Otherwise the receive side of the UART, _will_ hang.
It is really always far 'better' to use buffered interrupt driven receive, if you want to be sure of not missing anything. My guess would be that the other end sends a response when 'break' is seen (quite common - a lot of devices give back their ID, or initialisation message, when a break is sent), and your receive UART is getting hung up, because this is not being read.
Best Wishes |
|
|
ivojk
Joined: 20 Jun 2010 Posts: 6
|
RE |
Posted: Mon Jun 21, 2010 5:09 am |
|
|
Hi,
Thanks for reply
Can you show me simple example about right way to receive?
Maybe this code is good:
Code: |
char Buff;
char Counter;
#int_RDA
void RDA_isr(void)
{
disable_interrupts(GLOBAL);
Buff = getc();
put_usb(); // Send byte to PC by USB
enable_interrupts(GLOBAL);
}
|
BR |
|
|
Mcasclv
Joined: 21 Jun 2010 Posts: 1 Location: Barcelona
|
|
Posted: Mon Jun 21, 2010 12:19 pm |
|
|
Hello! We are trying to communicate with a PIC 18F2550 BQ2013.
In the communication we use the UART, 8 data bits by sending two stop bits no parity, and a baudrate of 57600, and asynchronous mode. It is necessary to send a break to start the communication.
The reception and transmission is made to a single pin of the bq2013 (HDQ protocol).
We managed to send data but only received the same as sent.
Code: |
#include <18F2550.h>
#device adc=8
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL3,CPUDIV1,VREGEN
#use delay(clock=48000000)
#use rs232(baud=57600,xmit=PIN_C6,rcv=PIN_C7,parity=N,bits=8,STOP=2,uart1)
/////////////////////////////////////////////////////////////////////////
#define USB_HID_DEVICE FALSE //deshabilitamos el uso de las directivas HID
#define USB_EP1_TX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE USB_ENABLE_BULK //turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE 2 //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE 2 //size to allocate for the rx endpoint 1 buffer
#include <pic18_usb.h> //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include <descriptor.h> //ConfiguraciĆ³n del USB y los descriptores para el dispositivo
#include <usb.c>
#byte TXSTA=0xFAC
#bit TXEN= TXSTA.5
#bit SYNC=TXSTA.4
#bit SENDB=TXSTA.3
#byte RCSTA=0xFAB
#bit SPEN=RCSTA.7
#byte SPBRGH=0xFB0
#byte SPBRG=0xFAF
#bit BRGH=TXSTA.2
#byte BAUDCON= 0xFB8
#bit BRG16=BAUDCON.3
#byte TXREG=0xFAD
#define LEDV PIN_B6
#define LEDR PIN_B7
#define TXPIN PIN_C6
#define RXPIN PIN_C7
#define LEDA PIN_B0
#define ENCENDER output_high
#define APAGAR output_low
#define control bufferI[0]
#define direccion bufferI[1]
#define dato bufferO[0]
#define datoHdq bufferII[0]
******************************************************
........
TXEN=1;
SYNC=0;
SPEN=1;
BRGH=1;
SPBRGH=8;
BRG16=0;
SendBreak();
TXREG=direccion;
datoHdq=getc();
.........
*****************************************
void SendBreak(void){
setup_uart(FALSE);
APAGAR(TXPIN);
delay_us(190);
ENCENDER(TXPIN);
delay_us(40);
setup_uart(TRUE);
set_uart_speed(57600);
}
|
Gracias!!! |
|
|
|