We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I cannot seem to get anything out of UART0 or 1 using printf(). What is the correct way to program these UARTS?
Thank you, Stephen Blair
What is the correct way to program these UARTS?
about 47 different ways
show your attempt and guidance will appear
Erik
I've got the uPSD3354 clocked by a TTL/CMOS powered 40MHz oscillator. In PSDsoft, I've got P1.3 set to TXD1 and P1.2 as RXD1. I've got P3.1 set to TXD0 and P3.0 as RXD0, with TXD0 going to a MAX232 to pin 11 and RXD0 going to pin 12. TXD0 out of the MAX goes to pin 2 while RXD0 in goes to pin 4.
TXD1 and RXD1 are not wired out yet because I'm going to wire them to a serial Caller ID chip and haven't figured out if I need to invert any of these signals.
I zipped up the code I'm using but don't know how to get it to you.
Sincerely, Stephen Blair
a MAX232 to pin 11 and RXD0 going to pin 12. TXD0 out of the MAX goes to pin 2 while RXD0 in goes to pin 4. pin numbrs are meaningless, they vary from package to package e.g. PQFP and DIL, use pin names.
I zipped up the code I'm using but don't know how to get it to you. just post the interesting parts here NOTE: no tabs, only spaces and bracketed with 'pre' as seen in the yellow above.
The hardware side is fine. I assume this because I am getting a constant stream of spaces through COM1.
Here's the relevent code:
/* Main.c v1.0 27 April 2008 Copyright 04/27/08, Stephen J. Blair Contains the main loop for the entire program */ #include "upsd3300.h" #include "upsd3300_hardware.h" #include "stdio.h" #include <main.h> #include <upsd_SIO.h> xdata volatile PSD_REGS PSD_reg _at_ PSD_REG_ADDR; // Access PSD regs at CSIOP addr main() { unsigned int count; InitIOpins(); com_initialize(); // initialize RS232 port TI = 1 ; count = 0; printf("\n\n"); printf("printf on uPSD UART0\n\n"); printf("Hello World\n"); while(1) { printf("Count = %x\n", count); count++; } } void InitIOpins(void) { PSD_reg.PMMR0|=0x08; // Disable PSD Module Turbo Mode to save power PSD_reg.PMMR2|=0x3C; // Set PSD Module PLD input blocking bits to save power // Block WR*, RD*, PSEN*, and ALE P1SFS0 = 0x0E; // Enable UART1 RX, TX on PORT 1 P1SFS1 = 0x00; // Don't enable any ADC's PORT 1 P3SFS = 0x07; // Enable UART0 TX, RX, and EXTINT1 PORT 3 P4SFS0 = 0x00; // Enable nothing on PORT 4 P4SFS1 = 0x00; // Enable nothing on PORT 4 PSD_reg.DIRECTION_A = 0xD9; // set port pins PA0, PA3, PA4, PA6, PA7 (11011001) as outputs PSD_reg.OUTENABLE_A = 0xD9; // enable port pins as outputs if bit = 1 PSD_reg.CONTROL_A = 0x00; // set all to default pin mode PSD_reg.DRIVE_A = 0x00; // set to default CMOS push-pull and normal slew rate PSD_reg.DATAOUT_A = 0x01; // set LC* off PSD_reg.DIRECTION_B = 0xF0; // set PB4..PB7 (A12..A15) as outputs PSD_reg.OUTENABLE_B = 0xF0; // enable port pins as outputs if bit = 1 PSD_reg.CONTROL_B = 0xF0; // set PB4..PB7 (A12..A15) as latched outputs - high nibble PSD_reg.DRIVE_B = 0x00; // set to default CMOS push-pull and normal slew rate PSD_reg.DATAOUT_B = 0x00; // set all OFF PSD_reg.DIRECTION_C = 0x80; // set no port pins as outputs PSD_reg.OUTENABLE_C = 0x80; // enable port pins as outputs if bit = 1 PSD_reg.DRIVE_C = 0x00; // set to default CMOS push-pull and normal slew rate PSD_reg.DATAOUT_C = 0x80; // set 12VPWRDN* to high PSD_reg.DIRECTION_D = 0x06; // set no port pins as outputs PSD_reg.OUTENABLE_D = 0x06; // enable port pins as outputs if bit = 1 PSD_reg.DRIVE_D = 0x00; // set to default CMOS push-pull and normal slew rate PSD_reg.DATAOUT_D = 0x06; // set DTMF CS* and the Status LED high } // EOF Main.c /* Main.h v1.0 27 April 2008 Copyright 04/27/08, Stephen J. Blair Header file for the main loop */ #ifndef _main_h_ #define _main_h_ #include "upsd3300.h" #include "upsd3300_hardware.h" void InitIOpins(void); #endif // EOF Main.h /*-------------------------------------------------------------------------- upsd_sio.c Version: October 27, 2004 Version 0.1 Dependencies: None. Description: UART0 Initialization routine. Note: the com_baudrate() function should be updated for more flexibility for setting the baud rate. Currently it is fixed and doesn't take into account FREQ_OSC found in upsd3xxx_hardware.h file. Copyright (c) 2004 ST Microelectronics This example demo code is provided as is and has no warranty, implied or otherwise. You are free to use/modify any of the provided code at your own risk in your applications with the expressed limitation of liability (see below) so long as your product using the code contains at least one uPSD product (device). LIMITATION OF LIABILITY: NEITHER STMicroelectronics NOR ITS VENDORS OR AGENTS SHALL BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA, INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. --------------------------------------------------------------------------*/ #include "upsd3300.h" #include "upsd_SIO.h" #define USE_TIMER2 //Select timer for baud rate generator #define BAUD_19200 //#define BAUD_115200 // setup TIMER1 to generate the proper baud rate void com_baudrate (void) { #ifdef USE_TIMER1 TI = 0 ; // set timer 1 up as a baud rate generator TR1 = 0; // stop timer 1 ET1 = 0; // disable timer 1 interrupt PCON |= 0x80; // 0x80=SMOD: set serial baudrate doubler TMOD &= ~0xF0; // clear timer 1 mode bits TMOD |= 0x20; // put timer 1 into MODE 2 // magic formula: (unsigned char) (256 - (OSC_FREQ / (16L * 4L * baudrate))); TH1 = -11; //for 19200 bps TL1 = 0x00; TR1 = 1; // start timer 1 #endif #ifdef USE_TIMER2 TI = 0 ; #ifdef BAUD_19200 RCAP2H = 0xFF;//Sets baud rate at 19200 RCAP2L = 0xBF;//for both UART0 and UART1 #endif #ifdef BAUD_115200 RCAP2H = 0xFF;//Sets baud rate at 19200 RCAP2L = 0xF5;//for both UART0 and UART1 #endif T2CON = 0x34; //Sets timer2 on, UART0 TCKL and RCKL, timer, reload SCON0 = 0x74; #endif } //------------------------------------------------------------------------------ // initialize the serial port void com_initialize (void) { com_baudrate(); // setup TIMER1 to generate the proper baud rate // setup serial port registers. SM0 = 0; SM1 = 1; // serial port MODE 1 SM2 = 0; REN = 1; // enable serial receiver TI = 0; // clear transmit flag RI = 0; // clear receive flag ES=0; //serial interrupts disabled PS=0; //serial interrupts - low priority IPA = 0x00; // reset others devices' priorities P3SFS |= 0x03; // enable alternative function (UART RX & TX) of P3 pins // Other uPSD init items... IE |= 0xC0; // Enable Global and Debug Interrupts... EA = 1; // enable interrupts } //------------------------------------------------------------------------------ // EOF // upsd_SIO.h // #ifndef __SIO_H__ #define __SIO_H__ void com_initialize (void); void com_baudrate (void); //void com_putstring (unsigned char *str, int len); //int com_getstring (char *buf); #endif // EOF upsd_SIO.h
P3.1 UART0-TXD to MAX232 T1IN to T1OUT to TXD on DB-9 P3.0 UART0-RXD to MAX232 R1OUT to R1IN to RXD on DB-9 DB-9 pin 5 to GND
are you using the correct cable, some connections need R and T crossed, some do not. If you use std DB9 pinning (BTW it is not a DB :), althought everyboddy and his brother calls it that) you need R and T crossed in the cable or T and T will connect.
I thought this might be it at first too, but the 4 port serial card takes care of the pin swapping.
Stephen; As Erik points out, you need to define your target board RS232 connections. I assume that you are building your target system and we are not talking of an eval board from some vendor. You need to decide if your system will be a DCE connection or a DTE connection. The PC is normally defined as a DCE and an eval board is defined as a DTE in which case the eval connections for Rx and Tx are reversed and you can use a straight through cable. If both ends are defined as DCE, then you will need a cable reversing pins Rx and TX called a 'Null Modem' connection. Google RS232 and you will get several hits on proper pin definitions. It sounds to me that you might want your target board defined as DCE so talking to a PC with something like Hyperterminal, you will need a Null Modem cable. Of course Hyperterminal doesn't care what connection you have. I was just using that as an example. But if you plan to connect to some accessory, it most likly will be a DTE and your target should be a DCE. Bradford
Stephen; I was out rambling with my typing and did not read your post about the four port card. Please disregard my post. Sorry about that. Bradford
My PC is DTE. Pin 3 on the DB9 is TXD. I verified this with my oscilloscope. I've got the uPSD3354D wire-wrapped and pin 2 on its DB9 is TXD. You definitely had me checking. It's been a while since I've worked with this board.
.. I can't say with certainty re printf.
BUT I rcall that printf uses putchar (which i don't use either) and tend to recall that there is something you need to do to "install" or "activate" it.
also, are you sure that TH1 = -11, TL1 =0 is correct verify using the Kiel budrate generator http://www.keil.com/c51/baudrate.asp
19.2 is impossible using T1, you need another xtal or use T2
I'm using Timer2 to get the 19,200 baud. I tried adding the line:
TI = 1;
before:
printf("Testing");
In the Keil simulator, I got "Testing" in the UART #1 debug window. On the actual board I keep getting a never ending stream of spaces.
The simulator will not have to decode the output from the simulated UART.
When testing serial communication on real hardware, you should always verify the baudrate with an oscilloscope. That will catch rounding or spelling errors that may result in incorrect baudrates. Even when the PC is able to receive data, the baudrate should be checked - only with a perfect baudrate will the receiver have maximum probability of correctly receiving the data in a noisy environment.
Anyway - if the PC only shows spaces, the scope should tell what is actually sent on the serial cable.