Jump to content

Search the Community

Showing results for tags 'pic'.

More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


  • Top Level
    • Announcements
    • The Lounge
    • Questions and Answers
    • Forum Help
    • Project Gallery
    • Vendor Bug Reports


  • What every embedded programmer should know about ...
  • Programming Lore

Find results in...

Find results that contain...

Date Created

  • Start


Last Updated

  • Start


Filter by number of...


  • Start



About Me

Found 21 results

  1. I just downloaded XC32 V2.15, I was using V2.10 before. I find that some of my projects no longer compile. On my first check I noticed that the problems seem to occur when inline functions are used and the same header where the inline implementation is done is included in more than one compilation unit? Has any of you seen similar issues? I will investigate further and post here if I arrive at an answer. UPDATE: Ok, I managed to make a small test project to replicate the problem. I am attaching it here. TestInlineXC32_2.15.zip Next I am going to test this on some other compilers to see what the deal is. I have confirmed that with that project when you switch it to V2.10 or older it all compiles just fine, but if you use V2.15 it failes to link with the following error: "/Applications/microchip/xc32/v2.15/bin/xc32-gcc" -mprocessor=32MZ2048EFM100 -o dist/default/production/TestInlineXC32_2.15.X.production.elf build/default/production/main.o build/default/production/otherFile.o -DXPRJ_default=default -legacy-libc -Wl,--defsym=__MPLAB_BUILD=1,--no-code-in-dinit,--no-dinit-in-serial-mem,-Map="dist/default/production/TestInlineXC32_2.15.X.production.map",--memorysummary,dist/default/production/memoryfile.xml nbproject/Makefile-default.mk:151: recipe for target 'dist/default/production/TestInlineXC32_2.15.X.production.hex' failed make[2]: Leaving directory '/Users/ejacobus/MPLABXProjects/TestInlineXC32_2.15.X' nbproject/Makefile-default.mk:90: recipe for target '.build-conf' failed make[1]: Leaving directory '/Users/ejacobus/MPLABXProjects/TestInlineXC32_2.15.X' nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed build/default/production/otherFile.o: In function `myInlineFunction': /Users/ejacobus/MPLABXProjects/TestInlineXC32_2.15.X/inlinedheader.h:6: multiple definition of `myInlineFunction' build/default/production/main.o:/Users/ejacobus/MPLABXProjects/TestInlineXC32_2.15.X/inlinedheader.h:6: first defined here /Applications/microchip/xc32/v2.15/bin/bin/gcc/pic32mx/4.8.3/../../../../bin/pic32m-ld: Link terminated due to previous error(s). collect2: error: ld returned 255 exit status make[2]: *** [dist/default/production/TestInlineXC32_2.15.X.production.hex] Error 255 make[1]: *** [.build-conf] Error 2 make: *** [.build-impl] Error 2 BUILD FAILED (exit value 2, total time: 680ms)
  2. If you have purchased a "MPLAB(R) Xpress PIC18F47K40 Evaluation Board" from Microchip (part number DM182027) and you are running into difficulty because the board is behaving strangely it is most likely caused by a silicon errata on this device! The errata can be downloaded here: http://ww1.microchip.com/downloads/en/DeviceDoc/PIC18F27-47K40-Silicon-Errata-and-Data-Sheet-Clarification-80000713E.pdf The relevant section of the Errata is shown at the end. What is happening is that the compiler is using a TBLRD instruction somewhere and this instruction is not behaving as expected due to a silicon bug in REV A2 of the PIC18F47K40, causing the read to fail and the program to malfunction. Typically this happens as part of the C initialization code generated by the XC8 compiler, and since the compiler is optimizing, changing the code may cause the problem to temporarily disappear because you have few enough global variables that a table read is no longer the fastest way to initialize the memory segment for variables with static linkage. The XC8 compiler can avoid generating the sequence which will cause the failure if you tell it in the linker settings to implement the workaround for this Errata. This is done by adding +NVMREG to the setting as follows. Note that this is under the section "XC8 Linker" and the Option Category "Additional Options". This is the relevant section of the Errata.
  3. I recently got my hands on a brand new PIC18F47K40 Xpress board (I ordered one after we ran into the Errata bug here a couple of weeks ago). I wanted to start off with a simple "Hello World" app which would use the built-in CDC serial port, which is great for doing printf debugging with, and interacting with the board in general since it has no LED's and no display to let me know that anything is working, but immediately I got stuck. Combing the user's guide I could not find any mention of the CDC interface or which pins to configure to make it work, so I stared at the schematic and identified a hand full of candidates which I could try as the correct pins. Eventually I figured it out, the TX pin to send data to the PC is RB6 and the RX pin which will receive data from the PC is RB7, so if you are setting up the UART using MCC it should look like this: I created a very simple little terminal application to test the board with and thought this may be something useful for others who start with this board, especially since the standard MCC UART code falls afoul of the dreaded Errata we discussed here before caught me out again even on this simple little application. So remember to set the linker up to implement the workaround for the Errata like so -> The little program simply waits for a keypress (so you have time to set up your terminal application) and then (at 115200 BAUD) sends the welcome message "Hello World". After this the program will echo every character you type, but it will enclose it in a message so that you are sure you are not just fooled by the local echo in your terminal program! Here is the whole program, the serial port and other setup is all generated using MCC. void main(void) { // Initialize the device SYSTEM_Initialize(); // Wait for a keypress before we start EUSART1_Read(); // Say Hello printf("Hello World\r\n"); while (1) { printf("Received: '%c' \r\n", EUSART1_Read()); } } The full example project can be downloaded from here ADC_47K40.zip Note: I have set the project up to automatically copy the hex file onto the board, programming it, when I build the code. This is however set up for my MAC, if you are no a PC or linux you will probably see an error when building that it could not copy the file. If you want to set this up for your platform the instructions are in the users guide for the board. I include a screenshot of the page here for convenience.
  4. Hello, I have run into a strange (for me) issue with the rtcounter module as provided by MCC and shown by the example program in the blog area of this site. I am using MPLabX and XC8, both up-to-date versions and I am trying the example on a pic18F47k40 xpress board. The issue is I set an output (RA4) in main after initializing the pic and then enter the while(1) loop where the rtcount_callNextCallback(); is called. The output now is turning on and off. The off duration is typically ~60u seconds, and on time can be varied with changes to the timer interrupt settings (I use a 1mS timer0 in 16 bit mode) and the number sent to the callback. Approximately every 3mS, the off time increases such that that cycle (only) is approx 50% duty cycle. Turning the output on or off in the callback routine has no effect - I initially wanted to toggle on and off at a speed visible to the eye. Commenting out the callback in the main loop stops the output from going low. I have checked errata and used the data sheet to confirm register settings, I tried moving the current-limited LED from RA4 to RA2, and I have studied the example program looking for obvious differences that may cause this behaviour. I would appreciate thoughts and/or suggestions. Keith
  5. Whenever I start a new project I always start off reaching for a simple while(1) "superloop" architecture https://en.wikibooks.org/wiki/Embedded_Systems/Super_Loop_Architecture . This works well for doing the basics but more often than not I quickly end up short and looking to employ a timer to get some kind of scheduling going. MCC makes this pretty easy and convenient to set up. It contains a library called "Foundation Services" which has 2 different timer implementations, TIMEOUT and RTCOUNTER. These two library modules have pretty much the same interface, but they are implemented very differently under the hood. For my little "Operating System" I am going to prefer the RTCOUNTER version as keeping time accurately is more important to me than latency. The TIMEOUT module is capable of providing low latency reaction times whenever a timer expires by adjusting the timer overflow point so that an interrupt will occur right when the next timer expires. This allows you to use the ISR to call the action you want to happen directly and immediately from the interrupt context. Nice as that may be in some cases, it always increases the complexity, the code size and the overall cost of the system. In our case RTCOUNTER is more than good enough so we will stick with that. RTCOUNTER Operation First a little bit more about RTCOUNTER. In short RTCOUNTER keeps track of a list of running timers. Whenever you call the "check" function it will compare the expiry time of the next timer and call the task function for that timer if it has expired. It achieves this by using a single hardware timer which will operate in "Free Running" mode. This means the hardware timer will never be "re-loaded" by the code, it will simply overflow back to it's starting value naturally, and every time this happens the module will count that another overflow has happened in an overflow counter. The count of the timer is made up by a combination of the actual hardware timer and the overflow counter. By "hiding" or abstracting the real size of the hardware timer like this the module can easily be switched over to use any of the PIC timers, regardless if they count up or down or how many bits they implement in hardware. Mode 32-bit Timer value General (32-x)-bit of g_rtcounterH x-bit Hardware Timer Using TMR0 in 8-bit mode 24-bits of g_rtcounterH TMR0 (8-bit) Using TMR1 16-bits of g_rtcounterH TMR1H (8-bit) TMR1L (8-bit) RTCOUNTER is compatible with all the PIC timers, and you can switch it to a different timer later without modifying your application code which is nice. Since all that happens when the timer overflows is updating the counter the Timer ISR is as short and simple as possible. // We only increment the overflow counter and clear the flag on every interrupt void rtcount_isr(void) { g_rtcounterH++; PIR4bits.TMR1IF = 0; } When we run the "check" function it will construct the 32-bit time value by combining the hardware timer and the overflow counter (g_rtcounterH). It will then compare this value to the expiry time of the next timer in the list to expire. By keeping the list of timers sorted by expiry time it saves time during the checking (which happens often) by doing the sorting work during creation of the timer (which happens infrequently). How to use it Using it is failry straight-forward. Create a callback function which returns the "re-schedule" time for the timer. Allocate memory for your timer/task and tie it to your callback function Create the timer (which starts it) specifying how long before it will first expire Regularly call the check function to check if the next timer has expired, and call it's callback if it has. In C the whole program may look something like this example: #include "mcc_generated_files/mcc.h" int32_t ledFlasher(void* p); rtcountStruct_t myTimer = {ledFlasher}; void main(void) { SYSTEM_Initialize(); INTERRUPT_GlobalInterruptEnable(); INTERRUPT_PeripheralInterruptEnable(); rtcount_create(&myTimer, 1000); // Create a new timer using the memory at &myTimer // This is my main Scheduler or OS loop, all tasks are executed from here from now on while (1) { // Check if the next timer has expired, call it's callback from here if it did rtcount_callNextCallback(); } } int32_t ledFlasher(void* p) { LATAbits.RA0 ^= 1; // Toggle our pin return 1000; // When we are done we want to restart this timer 1000 ticks later, return 0 to stop } Example with Multiple Timers/Tasks Ok, admittedly blinking an LED with a timer is not rocket science and not really impressive, so let's step it up and show how we can use this concept to write an application which is more event-driven than imperative. NOTE: If you have not seen it yet I recommend reading Martin Fowler's article on Event Sourcing and how this design pattern reduces the probability of errors in your system on his website here. By splitting our program into tasks (or modules) which each perform a specific action and works independently of other tasks, we can generate code modules which are completely independent and re-usable quite easily. Independent and re-usable (or mobile as Uncle Bob says) does not only mean that the code is maintainable, it also means that we can test and debug each task by itself, and if we do this well it will make the code much less fragile. Code is "fragile" when you are fixing something in one place and something seemingly unrelated breaks elsewhere ... that will be much less likely to happen. For my example I am going to construct some typical tasks which need to be done in an embedded system. To accomplish this we will Create a task function for each of these by creating a timer for it. Control/set the amount of CPU time afforded to each task by controlling how often the timer times out Communicate between tasks only through a small number of shared variables (this is best done using Message Queue's - we will post about those in a later blog some time) Let's go ahead and construct our system. Here is the big picture view This system has 6 tasks being managed by the Scheduler/OS for us. Sampling the ADC to check the battery level. This has to happen every 5 seconds Process keys, we are looking at a button which needs to be de-bounced (100 ms) Process serial port for any incoming messages. The port is on interrupt, baud is 9600. Our buffer is 16 bytes so we want to check it every 10ms to ensure we do not loose data. Update system LCD. We only update the LCD when the data has changed, we want to check for a change every 100ms Update LED's. We want this to happen every 500ms Drive Outputs. Based on our secret sauce we will decide when to toggle some pins, we do this every 1s These tasks will work together, or co-operate, by keeping to the promise never to run for a long time (let's agree 10ms is a long time, tasks taking longer than that needs to be broken into smaller steps). This arrangement is called Co-operative Multitasking . This is a well-known mechanism of multi-tasking on a microcontroller, and has been implemented in systems like "Windows 3.1" and "Windows 95" as well as "Classic Mac-OS" in the past. By using the Scheduler and event driven paradigm here we can implement and test each of these subsystems independently. Even when we have it all put together we can easily replace one of these subsystems with a "Test" version of it and use that to generate test conditions for us to ensure everything will work correctly under typical operation conditions. We can "disable" any part of the system by simply commenting out the "create" function for that timer and it will not run. We can also adjust how often things happen or adjust priorities by modifying the task time values. As before we first allocate some memory to store all of our tasks. We will initialize each task with a pointer to the callback function used to perform this task as before. The main program= ends up looking something like this. void main(void) { SYSTEM_Initialize(); INTERRUPT_GlobalInterruptEnable(); INTERRUPT_PeripheralInterruptEnable(); rtcount_create(&adcTaskTimer, 5000); rtcount_create(&keyTaskTimer, 100); rtcount_create(&serialTaskTimer, 10); rtcount_create(&lcdTaskTimer, 100); rtcount_create(&ledTaskTimer, 500); rtcount_create(&outputTaskTimer, 1000); // This is my main Scheduler or OS loop, all tasks are executed from events while (1) { // Check if the next timer has expired, call it's callback from here if it did rtcount_callNextCallback(); } } As always the full project incuding the task functions and the timer variable declarations can be downloaded. The skeleton of this program which does initialize the other peripherals, but runs the timers completely compiles to only 703 words of code or 8.6% on this device, and it runs all 6 program tasks using a single hardware timer.
  6. I was wondering if any of you have some ideas why we still see so many people using the PIC16F877 and the PIC16F877a for their projects? I can imagine that many schools and universities have programs that were based on this very old device but surely these guys must be updating their material from time to time? Today I would expect people to use something like the PIC16F18855 or something like that. The XPress evaluation board for that device is just $13 on Digikey ( link to Digikey ) and it does not even require a programmer to program the board (it has drag and drop programming via USB - the board shows up as a hard drive MSD device). Actually I think the PIC16F18875 is a better comparison as it has the same number of pins (40). So is any of you using the PIC16F877 and if so why that device? Just for the discussion here is how the devices stack up, with all the peripherals and extra RAM on the newer device I really cannot see how it makes sense to use the 877! What do you all think? PIC16F877 PIC16F18875 Digikey 1-off price $5.09 $1.67 Max Speed 20MHz 32MHz Flash 8k x 14 8k x 14 RAM 368 x 8 1K x 8 Package 40 PIN DIP 40 PIN DIP I/O Pins 33 36 Operating Range 4V-5.5V 1.8V-5.5V EEPROM 256x8 256x8 Peripherals CCP(2), MSSP(1), USART (1), TIMERS 8/16(2/1), CMP (2), ADC 10b(8 channels) CCP(5), PWM(2), MSSP (2), USART (1), TIMERS 8/16 (3/4), SMT Timer(2), ADCC 10b(35 channels), CLC (4), DSM(1), NCO (1), ZCD (1), CRC (1), CWG (3), CMP (2), DAC (1), VREF,
  7. I have a fairly general question for you all. I keep on running into situations where I need to mix C and ASM. Sometimes this works out easily by just using some asm("") instructions in the middle of my function, but sometimes I really feel like I could benefit from writing a function in ASM and calling it from C. I think my best example of this is the implementation of cryptographic functions such as AES or SHA. For these I see sometimes a 2x or even 3x speed improvement over what the compiler produces and I need to use these from more than one place so I really need a C function I can call to do these but I reallly need to implement it in ASM. Whenever I ask about mixing C and ASM I am told just not to do it, but it still seems to me that there are a lot of situations where this really is the best way to go? I recall a converstation with @holdmybeer where he needed very precise timing and the optimizer would always change the timing depending how the banks ended up being laid out (adding or removing bank switches), where implementing a function in ASM also seemed to be the solution. So I would like to get some opinions on this, do you guys agree? Any thoughts on this? PS. We recently had a related discussion about calculating parity as another example.
  8. error: variable has incomplete type 'void' If you are getting this error message trying to compile code that used to work or from some example code you found somewhere it is very likely because of the changes in the XC8 interrupt syntax introduced with V2.0 of XC8. Specifically I am getting this today for my interrupt service routine definition. I used to use the age-old way of doing this in XC8 as follows: // Old way to do this void interrupt myISR(void) { // Old way Interrupt code here } After the changes to the XC8 compiler which were mostly motivated to get better C standard compliance, particularly with C99, the syntax for that function should now use the commonly adopted concept of function declaration-specifier attributes, which traditionally start with 2 underscores and contains either a list of parameters in brackets or have empty brackets if no parameters are present. // New and improved and C99 compliant way to specify an interrupt service routine in XC8 void __interrupt() myISR(void) { // New and improved interrupt code here } This syntax is now also consistent between XC8, XC16 and XC32 Please see this post for more information on how to either work around this or change to the new syntax. https://www.microforum.cc/topic/5-i-used-to-use-to-locate-variables-but-since-xc8-20-this-is-no-longer-working/
  9. This is my attempt to convert the blazingly fast assembler routine for calculating parity into a C function. The original comes from here: https://www.microchip.com/forums/m4762.aspx Unfortunately Microchip have killed off the board where the original discussion took place at http://asp.microchip.com/webboard/wbpx.dll/~DevTools/read?21443,5 #include <xc.h> //returns 0x00 (even parity) or 0x80 (odd parity) unsigned char parity(volatile unsigned char dat) //("volatile" is required because no C code reads the parameter) { asm("swapf parity@dat,w"); //assume correct bank is still selected asm("xorwf parity@dat,w"); //W has 8 bits reduced to 4 with same parity asm("addlw 41h"); // bit 1 becomes B0^B1 and bit 7 becomes B6^B7 asm("iorlw 7Ch"); // for carry propagation from bit 1 to bit 7 asm("addlw 2"); // Done! the parity bit is bit 7 of W asm("andlw 80h"); // set NZ if odd parity, and leave 00 or 80 in W asm("return"); return 1; //dummy instruction to defeat "no return value" error } void main(void) { unsigned char idx=0; while(1) { PORTA = parity(idx); idx++; } } I'm not sure if there's a cleaner way to suppress the "no return value" error, without generating extra code.
  10. Version 1.0.0


    This zip file contains the project implementing Duff's Device using XC8 and a PIC16F18875 which goes with the Duff's Device Blog. The project can be run entirely in the simulator in MPLAB-X so no need to have the device to play with the code! See the blog for more details
  11. I am seeing weird behavior when I am using sprintf with my code, the code looks fine but it is printing junk! Here is an example program for a PIC16F18875 : #include <xc.h> #include <stdio.h> #include <stdint.h> char buffer[128]; void main(void) { uint32_t multiplier = 10; sprintf(buffer, "Value1 : %02d, Value2 : %02d, Value 3: %02d", 5*multiplier, 7*multiplier, 8*multiplier); NOP(); } The resulting string printed is this: Value1 : 50, Value2 : 00, Value 3: 70 Why is this happening?
  12. Hello, This forum is very refreshing - good content and respectful users! I have a good amount of experience with PIC products, but not full-time day in and day out. My question is regarding the pros and cons of using the advanced versions of the PIC16f family vs the 18f family. I really like the analog peripherals amongst other features and I wonder what others think for new project development? For example, I am looking at a redesign of a product that currently has been using the PIC16f887 for the last 5 years. I am looking at the PIC16f18877 as a replacement unit and have spent some time wading through the 600+(!) page data sheet looking for opportunities to simplify the original circuit design and take advantage of some of these features. I am not looking for a way to avoid reading the data sheet, just some other points of view. Keith
  13. I am not sure how to get started with I2C using a PIC16F18875 which I have on the HPC Curiosity Development board.
  14. Version 3.0.0


    This is the LAB manual for the 2018 masters class which showed how to use I2C and Timers on the HPC curiosity board. The last lab shows how to use the BLE Click board to connect to your cellphone and send the touch data over this channel.
  15. Did you guys see the new XPress Evaluation boards that Microchip are now selling. These boards are very cheap and pretty cool way to start. They do not need any programmer to get going (programmer is on-board) and they also implement a USB CDC interface so you can hook up printf to go to the serial port and get a console on your device going. If you are using MCC you can set all of this up without writing a single line of code! Pretty cool beginner board I think and they are going for $12 with an additional $3 discount running right until the end of 2018 ! The boards look like this : You can get them from Microchip Direct here : https://www.microchipdirect.com/product/search/all/DM182026
  16. I have an application using a PICmicrocontroller that cannot tolerate high voltage being applied to the circuit board for any reason. I want to program the PICmicrocontroller in the final circuit. Can I program a PICmicrocontroller without high voltage?
  17. I have a system where I am using a PICmcu as an I/O processor handling lots of real-time activities. My main processor is some larger ARM (like a Raspberry Pi). I could implement a boot loader on the PICmcu but that is very complex and uses code space. I would like to simply use low voltage programming (LVP) and teach my host CPU to program the PICmcu directly. How do I do this?
  18. I have an older 8-pin device (12F508) and I am unable to enter debug mode with my PICkit. What is going on?
  19. I have a bunch of old projects using the @ method to hard locate variables at a specific location in data memory, but since I upgraded to XC8 2.0 none of these are working any more! How do I do this with the latest compiler? I am using XC8 v2.xx. I also saw this error at my interrupt service routine and I suspect that this is the same problem. My interrupt code looks like this void interrupt my_isr(void) { ... my code here } error: variable has incomplete type 'void'
  20. Ok, so every time I set up a pin as an output MCC insists on making it "Analog". It looks like this setting has something to do with the ANSEL register, but surely an output is not Analog so why do they do this?
  21. I think this is probably the most common question we get from beginners. Everybody gets confused with LATx and PORTx and run into Read-Modify-Write issues, so how does this really work?
  • Create New...