|
|
View previous topic :: View next topic |
Author |
Message |
_olaf_
Joined: 24 Feb 2005 Posts: 32
|
Problem with RS232 Communication |
Posted: Wed Jun 25, 2008 1:53 am |
|
|
Hello,
I have a problem with the RS232 communication in my program. I searched in the forum for similar problems, but anything I found was the same code as I use.
Code of timer_01.h
Code: |
#use delay(clock=4000000)
#define LCD_DB4 PIN_A4
#define LCD_DB5 PIN_A5
#define LCD_DB6 PIN_C0
#define LCD_DB7 PIN_C1
#define LCD_E PIN_B0
#define LCD_RS PIN_B1
#define LCD_RW PIN_B2
#define Tast_1 52
#define Tast_2 53
#define Tast_3 54
#define Tast_4 55
#define DB6 56
#define DB7 57
#define Beleuchtung 58
#define /Bel_an 59
#define Ausgang 60
#define RS232_XMIT 62
#define RS232_RCV 63
#use rs232(baud=19200,parity=N,xmit=RS232_XMIT,rcv=RS232_RCV) |
C-Code of the program
Code: |
#include <16f873.h>
#include "C:\timer_01.h"
#include <stdio.h>
#include <string.h>
#include "Flex_LCD420.c"
void PIC_Initialisierung(void);
#fuses HS,NOWDT,NOBROWNOUT,NOPROTECT
#reserve 0x00A0
#reserve 0x00B0:0x00B3
#reserve 0x00C0:0x00C3
char ISR_Flags=0x00; // Flags für die Interruptroutinen
#Locate ISR_Flags = 0x00A0 //
#bit INTF_START = ISR_FLAGS.0
#bit INTF_RB = ISR_FLAGS.1
#bit INTF_DATOK = ISR_FLAGS.2
#bit INTF_Light = ISR_FLAGS.3
#bit INTF_TMREND = ISR_FLAGS.4
char RB_Taste=0x00;
#locate RB_Taste = 0x0A1
#bit Taste1=RB_Taste.0
#bit Taste2=RB_Taste.1
#bit Taste3=RB_Taste.2
#bit Taste4=RB_Taste.3
struct
{
unsigned Zeiteinstellung:1; // 1 Bit für die Initialisierungsanforderung
unsigned Konfiguration:1; // 1 Bit für die Manchester_Dekodierung
} Menu_Punkt;
unsigned int Timer2_Zaehlvariable=0x0000;
unsigned int Zehntel_Zaehler=0x0000;
unsigned int Sec_Zaehler=0x0000;
unsigned int Min_Zaehler=0x0000;
unsigned int STD_Zaehler=0x0000;
unsigned int Zehntelsekunde=0x0000;
unsigned int Sekunden=0x0000;
unsigned int Minuten=0x0000;
unsigned int Stunden=0x0000;
static int8 old_PortB;
#define first_bit(x) (x&0x1)
#define second_bit(x) (x&0x2)
#define third_bit(x) (x&0x4)
#define fourth_bit(x) (x&0x8)
#Locate Zehntel_Zaehler = 0x00B0
#Locate Sec_Zaehler = 0x00B1
#Locate Min_Zaehler = 0x00B2
#Locate STD_Zaehler = 0x00B3
#Locate Zehntel_Sekunde = 0x00C0
#Locate Sekunden = 0x00C1
#Locate Minuten = 0x00C2
#Locate Stunden = 0x00C3
void PIC_Initialisierung(void)
{
int i=0;
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_CLOCK_DIV_2);
setup_spi(FALSE);
setup_counters(RTCC_INTERNAL,RTCC_DIV_64);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_1,124,8);
setup_ccp2(CCP_OFF);
enable_interrupts(INT_RB);
enable_interrupts(INT_RDA);
lcd_init();
lcd_putc("\Timer V1.0\n");
lcd_putc("Taster gedrueckt ");
lcd_gotoxy(1,3);
lcd_putc("Std.");
lcd_gotoxy(6,3);
lcd_putc("Min.");
lcd_gotoxy(11,3);
lcd_putc("Sek.");
lcd_gotoxy(16,3);
lcd_putc("1/10");
Menu_Punkt.Konfiguration=1;
enable_interrupts(INT_TIMER2);
enable_interrupts(global);
}
#int_RB
RB_isr() {
int new_PortB;
int changes;
new_PortB=input_b();
INTF_RB=1;
changes=new_PortB^old_PortB;
changes=changes&new_PortB;
changes=changes>>4;
old_PortB=new_PortB;
if (first_bit(changes))
{
Taste1=1;
lcd_gotoxy(8,2);
lcd_putc("1");
printf("Taste 1 gedrückt\n");
}
if (second_bit(changes))
{
Taste2=1;
lcd_gotoxy(8,2);
lcd_putc("2");
printf("Taste 2 gedrückt\n");
}
if (third_bit(changes))
{
Taste3=1;
lcd_gotoxy(8,2);
lcd_putc("3");
printf("Taste 3 gedrückt\n");
}
if (fourth_bit(changes))
{
Taste4=1;
lcd_gotoxy(8,2);
lcd_putc("4");
printf("Taste 4 gedrückt\n");
}
return 0;
}
#int_TIMER2
TIMER2_isr() {
Timer2_Zaehlvariable++;
if (Timer2_Zaehlvariable==100)
{
Timer2_Zaehlvariable=0;
Zehntel_Sekunde++;
lcd_gotoxy(16,4);
printf(lcd_putc,"%2d",Zehntel_Sekunde);
}
if (Zehntel_Sekunde==10)
{
Sekunden++;
Zehntel_Sekunde=0;
lcd_gotoxy(16,4);
printf(lcd_putc,"%2d",Zehntel_Sekunde);
lcd_gotoxy(11,4);
printf(lcd_putc,"%2d",Sekunden);
}
if (Sekunden==60)
{
Minuten++;
Sekunden=0;
lcd_gotoxy(11,4);
printf(lcd_putc,"%2d",Sekunden);
lcd_gotoxy(6,4);
printf(lcd_putc,"%2d",Minuten);
}
if (Minuten==60)
{
Minuten=0;
Stunden++;
lcd_gotoxy(6,4);
printf(lcd_putc,"%2d",Minuten);
lcd_gotoxy(1,4);
printf(lcd_putc,"%2d",Stunden);
}
return 0;
}
void main()
{
char i;
int I_RB_Count=0;
old_PortB=input_b();
switch ( restart_cause() )
{
case WDT_FROM_SLEEP: {
lcd_putc("\fFehlerfall\n");
}
case WDT_TIMEOUT: {
}
case NORMAL_POWER_UP: {
PIC_Initialisierung();
}
}
}
delay_ms(100);
SET_TRIS_A(0x00);
SET_TRIS_B(0xf0);
SET_TRIS_C(0x40);
i=0;
Menu_Punkt.Konfiguration=0;
while(1);
} |
Everything in the program works fine except the RS232 communication. I don't get any character on the PC. The only character I get is "<0>". What could be the problem? I tried it with Timer2 disabled and Baudrates down to 2400 baud. But this wasn't successful. I have checked the hardware but it should work.
Any other idea?
Best regards
Olaf |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jun 25, 2008 11:19 am |
|
|
Quote: |
setup_timer_2(T2_DIV_BY_1,124,8);
setup_ccp2(CCP_OFF);
enable_interrupts(INT_RB);
enable_interrupts(INT_RDA); |
You are enabling RDA interrupts, but you don't have an #int_rda function.
This is very bad. Delete the line shown in bold.
Quote: | #define Tast_1 52
#define Tast_2 53
#define Tast_3 54
#define Tast_4 55
#define DB6 56
#define DB7 57
#define Beleuchtung 58
#define /Bel_an 59
#define Ausgang 60
#define RS232_XMIT 62
#define RS232_RCV 63 |
Here you have tons of magic numbers. This is a bad programming technique. It makes the program difficult to understand and to maintain.
Use the CCS pin numbers from the 16F873.h file. Example:
Code: | #define Tast_1 PIN_B4
#define Tast_2 PIN_B5
#define Tast_3 PIN_B6
#define Tast_4 PIN_B7
#define DB6 PIN_C0
etc. |
With this method, it's very clear which pins are used by your program.
Here is an explanation of magic numbers:
http://c2.com/cgi/wiki?MagicNumber
Quote: | #Locate ISR_Flags = 0x00A0 //
char RB_Taste=0x00;
#locate RB_Taste = 0x0A1
#bit Taste1=RB_Taste.0
#bit Taste2=RB_Taste.1
#bit Taste3=RB_Taste.2
#bit Taste4=RB_Taste.3
#reserve 0x00A0
#reserve 0x00B0:0x00B3
#reserve 0x00C0:0x00C3 |
All of this "locate" and "reserve" stuff is unnecessary with CCS.
The CCS compiler will automatically put your variables in a suitable
location. You don't have to worry about it.
Quote: | #fuses HS,NOWDT,NOBROWNOUT,NOPROTECT |
You need to add the NOLVP fuse to the list. If you don't have it,
the PIC can lock-up if pin B3 goes to a high level. In recent versions
of the CCS compiler, CCS automatically sets NOLVP even if you don't
specify it. But you didn't give your compiler version so I'm telling
you about the need for NOLVP, in case you have an older version.
Quote: | SET_TRIS_A(0x00);
SET_TRIS_B(0xf0);
SET_TRIS_C(0x40); |
You are not using #fast_io() on any of those ports, so the compiler will
override those TRIS statements as needed. But you don't need to set
the tris, because the CCS compiler automatically sets the TRIS for you
if you use CCS pin i/o functions or CCS library functions. You can
delete the 3 lines shown above.
Quote: | #int_RB
RB_isr() {
return 0;
} |
Interrupt service routines don't return anything. Delete the line shown in bold.
Quote: | unsigned int Timer2_Zaehlvariable=0x0000;
unsigned int Zehntel_Zaehler=0x0000;
unsigned int Sec_Zaehler=0x0000;
etc. |
In CCS, an "unsigned int" is an 8-bit unsigned variable. Your code
implies that it is 16-bits, when you initialize it to 0x0000. If you want
16-bit unsigned variables, then declare them as "int16".
Finally, if you have an RS-232 problem, then first make a small test
program that only tests the RS-232 connection to the PC. Don't test
anything else in that program. See the 2nd post in the following link
for an example:
http://www.ccsinfo.com/forum/viewtopic.php?t=34127&highlight=putc+getc |
|
|
_olaf_
Joined: 24 Feb 2005 Posts: 32
|
|
Posted: Wed Jun 25, 2008 12:18 pm |
|
|
I have forgotten to handle the RDA interrupts so I don't enable them, o.k.
The defining of the different ports was not fully done. As you see, some of them are defined with the names in the PIC-headerfiles. But at the beginning it is easier for me, to see what register address is used.
I know, that (nearly) every compiler can locate variables on his own. But I wanted these addresses and therefore I specified them.
The NOLVP fuse was set by the compiler (Version 3.223) so I didn't had it in the #fuse declaration.
That the Tris statement is not needed is new to me (and I did not see similar with other compilers, most need the "Tris" statement e.g. GCC for Atmel controller). And in many posts it is used. But what does the compiler do if he does not have the Tris statement. Is then the Tris register set and reset every time when I change the direction of the data I/O?
The "return 0;" I inserted, because without this I get the warning:
Function not void and does not return a value
With the returnvalue I don't get the warning
I had in mind that an int was 16bit. And as I have learned in the last few minutes, it can be nearly everything from 8bit to 32bit depending on what kind of compiler/software you use
So I will now try a small simple program and test it. I thought, that I write my program in steps and ad every day a new part (yesterday it was the RS232-day ).
Olaf |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jun 25, 2008 12:40 pm |
|
|
Quote: | The NOLVP fuse was set by the compiler (Version 3.223) so I didn't had it in the #fuse declaration. |
That's not true. Here is your #fuses statement:
Code: | #fuses HS,NOWDT,NOBROWNOUT,NOPROTECT |
I compiled your program with vs. 3.223, and with that #fuses statement,
the .LST file shows these settings at the end of the file:
Quote: | Configuration Fuses:
Word 1: 3FBA HS NOWDT NOPUT NOPROTECT NOBROWNOUT LVP NOCPD NOWRT NODEBUG |
To fix this, you must add the NOLVP fuse as shown in bold below:
Quote: | #fuses HS,NOWDT,NOBROWNOUT,NOPROTECT, NOLVP |
Quote: | But what does the compiler do if he does not have the Tris statement.
Is then the Tris register set and reset every time when I change the direction of the data I/O? |
Yes, it sets the TRIS everytime you use output_low() or output_high(),
or output_b(), or any other pin i/o function.
Quote: | The "return 0;" I inserted, because without this I get the warning:
Function not void and does not return a value |
The correct way to get rid of the warning is to declare the function to
return 'void' as shown in bold below:
Quote: | #int_RB
void RB_isr() { |
|
|
|
_olaf_
Joined: 24 Feb 2005 Posts: 32
|
|
Posted: Wed Jun 25, 2008 1:17 pm |
|
|
Quote: |
Quote:
The NOLVP fuse was set by the compiler (Version 3.223) so I didn't had it in the #fuse declaration.
That's not true. Here is your #fuses statement: Code:
#fuses HS,NOWDT,NOBROWNOUT,NOPROTECT
I compiled your program with vs. 3.223, and with that #fuses statement,
the .LST file shows these settings at the end of the file: Quote:
Configuration Fuses:
Word 1: 3FBA HS NOWDT NOPUT NOPROTECT NOBROWNOUT LVP NOCPD NOWRT NODEBUG
|
Then we have a problem. If I compile the code without "NOLVP" and look at the Configuration Bits in MPLab, the LVP is disabled.
And the option for the configuration-bits window is set to "Configuration Bits set in code" in the MPlab (8.02) configuration bits window. Every change I make in the code e.g. change from HS to XT or change the Brownout-fuse is changed in the configuration bit window except the change of the NOLVP. This is unchanged. It still says "Low Voltage program" disabled
Olaf |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jun 25, 2008 4:47 pm |
|
|
I don't have MPLAB 8.02. I have 8.10 on another computer. I installed
PCM vs. 3.249 on that computer and compiled a test program without
the NOLVP fuse. The Configuration Bits menu in MPLAB shows:
Code: |
Low Voltage Program Enabled |
That is correct.
This option is also enabled:
Code: | [x] Configuration bits set in code |
I don't have a problem. I don't know what is causing your problem.
Maybe re-install everything or upgrade MPLAB. Or ask a question
about it on the MPLAB forum. |
|
|
Ttelmah Guest
|
|
Posted: Thu Jun 26, 2008 2:41 am |
|
|
Is it possible that some form of ICD is being used?.
I have seen MPLAB ignore the LVP fuse, when some types of ICE/ICD are being used.
It can be quite annoying, since if you forget to set the fuse the way it is needed, code that runs in the development environment, then doesn't work on the real chip...
Best Wishes |
|
|
|
|
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
|