RS232 Terminal with PIC microcontroller intermittent problem. - Page 1
Forum section: electronics / general

author: Dukov Ahzrukhal
author_rank: Regular Contributor
timestamp: June 10, 2018, 03:21:51 pm
content: Hello, I recently made a post about using a standard 16*2 LCD display with PIC microcontrollers. I now have that part figured out and I wrote a working LCD "library" for my projects. The problem im having is once I added a function to receive data from a PS/2 keyborad everything broke. Sometimes when I power on my project it works just fine, other times I get the initial message displayed correctly followed by a single random character and then the program doesnt respond any more. I thought it could be a simple issue like an uninitialized register, but I think im initializing everything correctly, and I even made my startup delay longer to be sure but that made no difference at all. Could it be just a silly mistake in the way I added in my new functions? or possibly a hardware issue? I will upload my broken code as well as the working test code for the LCD functions. The circuit is described in the comments.Thanks for helping.

author: Dukov Ahzrukhal
author_rank: Regular Contributor
timestamp: June 10, 2018, 06:15:03 pm
content: I have made a slight change the the KB_READ subroutine, and now the program is usable. It receives from RS232 when the DTR signal is set and reads from the keyboard otherwise. The keyboard doesn't actually work though, but that doesn't worry me because I didn't properly initialize it so that was to be expected. My real problem is that there is still a random character that gets printed after the first message and I cant figure out why. I will attach my new code.

author: TomS_
author_rank: Frequent Contributor
timestamp: June 13, 2018, 01:37:39 pm
content: Your PIC has a UART peripheral, why dont you use this instead of bit banging one? You can then use an interrupt to output received characters to the display once they have been received. This frees the MCU to do other things for the relative eternity in between.I had a quick look, but I cant particularly see why a random character would be displayed on the LCD.Perhaps its time to strip back to basics, and build up until you find a piece of code which introduces the random character. At least then you will know where to focus your debugging efforts.

author: Dukov Ahzrukhal
author_rank: Regular Contributor
timestamp: June 13, 2018, 03:50:44 pm
content: Thank you for the reply. I think using the UART in the chip is an excellent recommendation, however the reason why im not using it is that initially I had planned to use the PIC16F84A which doesnt have an UART. So I wrote a simple RS232 interface and since that part seems to be working just fine I have decided to stick with it. I never did figure out why the that random character shows up, I made a lot of changes and added more functionality but even now that everything is usable that random character keeps pestering me. I did find a very nasty bug in my KB_SEND function, which was that I was not allowing enough time for the keyboard clock transistor to switch off before polling the clock line. there were other bugs too, but nothing that would make a random character show up on the display. I will attach my current version of the project, it all works except I still haven't added in the function to translate keyboard scan codes to ASCII and the initial message is still being replaced with one or more (sometimes blank) random characters.I think its time for me to acquire a logic analyzer and see whats being sent to the display..

author: TomS_
author_rank: Frequent Contributor
timestamp: June 13, 2018, 04:14:16 pm
content: If youre going to build a project that needs a UART, use a PIC that has a UART peripheral. Life is too short to go implementing this kind of stuff in software, and then having to try and debug it.For hobby use, get yourself some capable devices that will let you do anything you might want to do. In the range you are working in, something like a 16F886 for example (https://www.microchip.com/wwwproducts/en/PIC16F886). I can get a pack of 5 for about £10 for example. If you ever do anything for production you can then look at choosing a lower spec device which better matches cost and other considerations.Try something simple, does the random character appear if you only display the initial message on the LCD, and dont include any of the UART or keyboard stuff?

author: Dukov Ahzrukhal
author_rank: Regular Contributor
timestamp: June 13, 2018, 04:47:15 pm
content: I must have made a stupid mistake, I set this up so that everything will be initialized and the initial message will be printed but the program will stop before entering the main loop. This is to test the initial message without calling any other functions like you said (other than KB_INIT which is called before the initial message is printed). Now, this did get rid of the random character but also the initial message was not printed. The display was properly initialized and I can see the blinking cursor but no characters appear. I did just change the initial message to make use of the print function, but I don't think that made any difference. I probably just forgot to set the display RS or R/W signals somewhereI'll attach the code I just tested and ill be checking to see if can find my mistake somewhere.

author: Dukov Ahzrukhal
author_rank: Regular Contributor
timestamp: June 13, 2018, 05:34:51 pm
content: Is there something wrong with my DUKOV function? from what I see on the logic analyzer it looks like the display is first initialized as expected, then cleared, and then a single character is printed. this must be from the table, but the character that appears is not on the table. I really don't get this nowEDIT: I see an issue, I moved the table with the text to be right below the DUKOV function and now it actually prints what its supposed to, but it also prints an extra 0x00 at the end (I think its the zero at the end of the table). I cant explain how this is happening...

author: TomS_
author_rank: Frequent Contributor
timestamp: June 13, 2018, 06:05:49 pm
content: In DUKOV2, do you perhaps want to XORLW instead of XORWF? By specifying 00 as the operand for XORWF you are telling it to XOR W with the contents of memory address 00. As it is, if memory address 00 is not a zero, then the result is likely to be non-zero and hence you will branch straight to STOP. Memory address 00 seems to be the INDF register, and a quick glance at the datasheet suggests maybe you dont want to be using this...Alternatively, since you are only wanting to affect the Z status bit to test for zero, I would use MOVF to move a register in to itself instead. If the contents were zero then Z is set and you havent modified any contents.Also, for many of your instructions, I would highly recommend using the W and F mnemonics instead of 1 or 0 for the destination to make your code more readable. e.g.INCF MSG_COUNT,1becomesINCF MSG_COUNT,Fand it is easier to tell at a glance where the result of the operation should be stored.

author: Dukov Ahzrukhal
author_rank: Regular Contributor
timestamp: June 13, 2018, 06:09:26 pm
content: Yep, that was itSorry.EDIT: I'm out of blank chips, I'm going to erase some and test the rest of the code. What an embarrassing bug, thanks for catching it.

author: TomS_
author_rank: Frequent Contributor
timestamp: June 13, 2018, 09:12:31 pm
content: Quote from: Dukov Ahzrukhal on June 13, 2018, 05:34:51 pmThis might have something to do with memory paging. Refer to page 48 ofhttp://ww1.microchip.com/downloads/en/DeviceDoc/30234E.pdf.

author: Dukov Ahzrukhal
author_rank: Regular Contributor
timestamp: June 13, 2018, 10:12:11 pm
content: Very interesting note. I don't need to worry about this right now because my code is less than 2K, but if I did need this later how would I actually go about calling a subroutine in a different page?

author: Dukov Ahzrukhal
author_rank: Regular Contributor
timestamp: June 14, 2018, 01:11:39 am
content: I am very confused. I fixed that pesky bug I had in the DUKOV function and tested the rest of the code I have posted so far. It all worked perfectly, but when I tried adding in my KB_TRANSLATE function everything (I do mean literally everything except the initial message) broke. I looked at my code and found some silly bugs, but still it wouldn't work. Finally I decided to move the KB_TABLE subroutine to the the top of the program (right after the INITIALIZE routine) because I had the feeling that might fix it and it did.Now I have two files that differ only in the location of KB_TABLE, one works and one doesn't, but I have no idea why.I could simply use the one that is working but I really want to know why the other one is not working because otherwise its a matter of time before I make some little change and everything breaks again. I will attach the working and non working versions of my code.

author: TomS_
author_rank: Frequent Contributor
timestamp: June 14, 2018, 06:44:06 am
content: The assembler listing file may help here. Page 48 suggests that a table should be located at a memory address such that no part of it extends beyond a 256 instruction block, e.g. if it starts at address F0 and is 32 instructions long then it ends at 10F, exceeding the first 256 instruction block which ends at FF.But why might they mention this explicitly? I couldimaginethis might be because adding to PCL perhaps does not effect a carry to higher program counter bits when it overflows, so when you compute the address of your RETLW the effective memory range of your "table" might actually end up being F0-FF and then 00-0F in practice. This may produce undesirable results if you start executing other pieces of code from the lower memory address for example, despite the rest of the table physically being in higher memory addresses.But read the application note that is mentioned in the datasheet to see what it says, as the above just a hunch and may be completely incorrect. The listing file produced by the assembler will show where it has placed your code in memory so you'll be able to see if your table stretches across a 256 word block, and you can use the ORG keyword to start it at a specific memory address where this won't happen.

author: TomS_
author_rank: Frequent Contributor
timestamp: June 14, 2018, 09:02:00 am
content: Quote from: Dukov Ahzrukhal on June 13, 2018, 10:12:11 pmIve never actually done it before personally, but I took a look at AN556 and I think what you need to do is load PCLATH with the upper bits of the address of the destination routine. When you do a CALL, those bits are then loaded in to the program counter along with the lower bits.Doesnt seem all that difficult, but it is a manual step that needs to be performed by the user, so I guess its open to error and head scratching.

author: TomS_
author_rank: Frequent Contributor
timestamp: June 14, 2018, 09:56:31 am
content: And yes, also according to AN556, and since the PIC16 family is an 8 bit processor family, incrementing PCL enough such that it overflows will simply wrap the value of it around on an 8 bit boundary. So tables need to be appropriately placed within memory so that they do not exceed blocks of 256 instructions.Use the ORG keyword to align it somewhere in one of the higher memory pages, and load PCLATH appropriately before doing a CALL would seem to be the way to do it. This way you can keep your tables out of the way of the majority of your code in lower memory pages.

author: Dukov Ahzrukhal
author_rank: Regular Contributor
timestamp: June 14, 2018, 09:27:46 pm
content: I changed all the tables so that they are in the first 256 words of program memory and now everything is working perfectly. I even added in more functionality (the shift keys work) and still nothing broke.I did catch a few little bugs but it was all mostly incorrect values in the KB_TABLE or not ignoring scan codes that should be ignored at the moment. I'll attach the working code and keep adding more functionality until something breaks lol.