| 
	
	|  |  |  
	
		| 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
 
 |