PIC my way through serial comms - Page 1
Forum section: electronics / general

author: PerranOak
author_rank: Frequent Contributor
timestamp: August 19, 2020, 03:31:28 pm
content: I have come to a watershed in my PIC learning.I've gone through my course that I purchased online: it's a sort of "grown-up" version of Arduino. You get: books, a programmer board (though it also uses MPLAB and PicKit for some things) and the various components for projects. I've completed the books/projects on: "PIC assembly", "C for PICs" and was working through the "serial comms for PICs" book when I realised that it is going in a different direction from what I want. It concentrates on fancy C# (Visual Studio) programmes that are too pretty and fussy for me and also a proprietary and non-general USB interface system.What I want from the comms element is:1. to be able to get the data stored in a PIC project (on-board EEPROM, say) onto a PC (then to, say, Excel), e.g. temperature data2. to send simple instructions to the PIC from the PC (Windows10Pro BTW)3. to send data to/from peripherals such as sensors4. to understand UART, I2C, SPII have a PicKit3 and MPLAB IDE and I rather like assembly as it helps me understand properly how things (e.g. registers) work.Could I ask for some recommendations of how to proceed please. I like to have an orderly schedule of learning rather than a piecemeal Googling of various bits and pieces.Thank you.

author: dmendesf
author_rank: Frequent Contributor
timestamp: August 19, 2020, 04:10:53 pm
content: Realistically the way to send data from PIC to PC is thru USB. You can hang a serial->usb converter in the PIC's serial port and use any terminal program to talk to it. There's probably some serial examples in your books. Next step is to get rid of the serial-usb converter: you can get a PIC with usb hardware like pic18f4550 and use an USB stack to emulate a serial port. Trust me, this is already a big jump if you don't have a good "how to". This will also depend on your compiler (I like CCS, but you're probably using the vendor tools). Don't try to learn every bit of what's going on at the USB side before using the stack... You will stay 6 months on it. It's a mess.

author: Buriedcode
author_rank: Super Contributor
timestamp: August 19, 2020, 04:13:14 pm
content: Quote from: PerranOak on August 19, 2020, 03:31:28 pmIf you cannot find a specific course, then organizing what you want to achieve and "googling" each part as you go, can still be effective. As with all problem solving its about breaking things down into smaller steps that can be gone through linearly, building up "blocks" and one by one putting them together. This is essentially what courses do, structure things for the student, but I dont' see why you can't do this yourself if you have a nice specific end goal - say a project that uses a PC to control a PIC data logger. Whilst its nice to "learn" a lot in one go, you will always have to google something: pinouts, errata, register names/bits/functions, so learning on the fly is arguably a better way.I learnt far more about microcontrollers by picking a specific project (like a remote control decoder) and breaking the problem down into modules and tests of those modules (over a months) than I did in my entire university degree.I know you said you like assembly, and I realize others may try to steer you away, but unless you're creating your own MCU's in FPGA's, I don't see much benefit to using assembly. Most of it is just moving data to and from the working register, checking the status register for comparisons etc.. and it becomes quite unwieldy one you get into using nested subs or calling multiple functions. Cis great and every compiler I am aware of allows inline assembly should you require single instruction precision timing.

author: ggchab
author_rank: Frequent Contributor
timestamp: August 19, 2020, 04:17:47 pm
content: I also like programming 8 bit PIC in assembly. Personally, I always started with the datasheet and was always able to make my code work pretty well. Not always successful the first time, but understanding my mistakes is one of my best ways to gain experience. UART, SPI and I2C PIC modules are not difficult to understandTo communicate with PC, you can use a USB to serial cable or an equivalent module in your project.For 16-bit devices, I use the code (in C) produced by MCC as a starting point, and then write my own libraries.I'm a hobbyist, so most of my projects are for fun

author: Ian.M
author_rank: Super Contributor
timestamp: August 19, 2020, 04:38:58 pm
content: Doing anything useful with PC to MCU comms entirely in assembly language is a P.I.T.A that will take an enthusiastic youngster and spit them out as a bald grey-beard, with a beard they can tuck into their belt! Bald, because they've torn out their hair from frustration, and beard in the belt because along the way, due to the hyper-focus required to get anywhere, personal grooming dropped off their priority list.The *EASY* way forward is to use a terminal program on the PC so you don't have to master the grand arcania of accessing PC com ports or USB devices from your own PC code, a USB<=>UART bridge chip (e.g. one of FTDI's many offerings or a CH340G, probably for convenience, as a cable or pre-built module), and then you only have to spit out data via the PIC USART at a baud rate the USB<=>UART bridge chip can handle, and formatted so its easy to import into Excel (or for whatever your intended end use is). Then you select the block of data in the terminal and either save it to open in Excel or copy/paste it straight to Excel.It gets tougher when you want to automate the process. Short of using a scriptable terminal you are going to have to delve into accessing COM ports from the .net family of languages, which is an adventure in its own right. Only masochists would consider doing the PC side in assebly language!*WAY* back in the day, I wrote PC code that talked to a device hanging off a COM port, and provided an OLE data source that could be linked to Excel cells which was a very steep learning curve. Even five years later, I'd have had to re-do it from scratch due to the rapid moving target that was Windows development from the 90's until relatively recently with Microsoft's Win10 rollout and shift towards Software as a Service.If you are determined to jump down the PIC18 assembly language USB device rabbit hole, google:brad minch assembly usb stackI doubt anyone's done anything serious with Brad's code for the best part of the last decade, so finding all the resources is going to be a battle against internet bit-rot.

author: rstofer
author_rank: Super Contributor
timestamp: August 19, 2020, 05:10:44 pm
content: I use a terminal program like PuTTY all the time to work with uC's and FPGAs. C# will wrap a GUI around the communications and you can have interactive commands execute when a button is clicked. But that's a much higher level and can be delayed, probably indefinitely.The thing is, your problems are at a medium level. You want to send commands? Great! How do you shut down the continuous sending of data? How do you tell the PIC it is time to pay attention to commands? Is serial IO interrupt driven and placed in a queue on the PIC? That kind of thing allows the PIC to deal with commands as it wanders through the inevitable super loop.Part of the solution is to create a 'language' (nothing more than a set of commands) that both ends agree to use. Clearly, you need to use some kind of ^C character to tell the PIC to stop sending routine data and pay attention for commands.Then you need to decide which commands to implement and what you expect the PIC to do about them. Once you have this all blocked out, you are off to the races in terms of coding.

author: ggchab
author_rank: Frequent Contributor
timestamp: August 19, 2020, 06:58:48 pm
content: TeraTerm is also good, simple and free.I use commands like "SET ...", "GET ...", ... Characters are pushed in a buffer via interrupts. When an end of line character is received, a flag is set. One of the tasks of the main loop it to look at this flag, analyze the command, call the right function and return a result. Other tasks may be updating a display, reading buttons, doing other things like reading a temperature, ...Results may also be placed in a buffer and sent via via interrupts.Main loop can be very well organized and simply do calls to functions (tasks).Again, if this is a hobby and you like doing assembly, you will have a lot of funSome time ago, I started learning 16 bit PIC and program them in C. Also a lot of fun !

author: PerranOak
author_rank: Frequent Contributor
timestamp: August 20, 2020, 10:57:56 am
content: Thanks all.I see the point about having a project and working through it but is there a book or a website or something I could use to get a start?I've got an Arduino but it's even worse for "doing everything for you".

author: Dabbot
author_rank: Regular Contributor
timestamp: August 20, 2020, 11:40:16 am
content: https://www.gooligum.com.au/PIC-tutorials

author: TomS_
author_rank: Frequent Contributor
timestamp: August 20, 2020, 11:45:19 am
content: You may not like the direction the course is going, but if it covers the basics, then you can build up from there.Learning how to use the UART to communicate, even if its not in the way you want to, will at least give you some knowledge to take with you on your own journey.Then again, if youre impatient like me and just want to get towards your end goal of reading temperature data and plotting it in a spreadsheet, you might just need to take the piecemeal approach and work out how to do the 3-4 specific things that you need to achieve that goal.I dont know if there will be a specific tutorial of "do a, b, c to read temperatures, send them to a PC and plot in a spreadsheet", but it doesnt sound too far off what a lot of people try to do as one of their first projects, so surely someone has something rouhgly in the ball park, maybe even on YouTube.

author: Dabbot
author_rank: Regular Contributor
timestamp: August 20, 2020, 11:54:12 am
content: If you are interested, I can share some assembly code I use to work with the EUSART peripheral on various PIC chips. It includes interrupt handlers and circular buffers for moving data back and forth with interrupt safe routines, which I often use as a template for more specific work.

author: NorthGuy
author_rank: Super Contributor
timestamp: August 20, 2020, 12:48:59 pm
content: Eventually, you will run out of tutorials and will have to go on your own. The sooner you learn how to do this the better.

author: PerranOak
author_rank: Frequent Contributor
timestamp: August 20, 2020, 01:45:49 pm
content: NorthGuy: sure but I've never even done it once ... I'm a serial comms virgin!Dabbot: that's great, thank you very much. I learn better with examples.

author: Dabbot
author_rank: Regular Contributor
timestamp: August 20, 2020, 02:18:02 pm
content: Enjoy!Note: This is PIC XC8 assembly, not MPASM (which is now retired). But it's similar enough not to matter.Code:; ********** 16F18326 EUSART **********; Build command:; "C:\Program Files\Microchip\xc8\v2.20\pic-as\bin\pic-as.exe" -xassembler-with-cpp "16F18326_EUSART.asm" -mcpu=16F18326 -Wl,-Map="16F18326_EUSART.map" -Wl,-PRES_VECT=0000h -Wl,-PINT_VECT=0004h; Processor selectionPROCESSOR 16F18326;PROCESSOR 16F18346; Configuration for PIC16(L)F18326 / PIC16(L)F18346; Config bits for register: CONFIG1 @ 0x8007; FEXTOSC: External Oscillator mode Selection bits;CONFIG FEXTOSC = ECH; EC (external clock) above 8 MHz;CONFIG FEXTOSC = ECM; EC (external clock) for 100 kHz to 8 MHz;CONFIG FEXTOSC = ECL; EC (external clock) below 100 kHz;CONFIG FEXTOSC = HS; HS (crystal oscillator) above 4 MHz;CONFIG FEXTOSC = XT; XT (crystal oscillator) from 100 kHz to 4 MHz;CONFIG FEXTOSC = LP; LP (crystal oscillator) optimized for 32.768 kHzCONFIG FEXTOSC = OFF; External oscillator not enabled; RSTOSC: Power-up default value for COSC bits;CONFIG RSTOSC = EXT1X; EXTOSC operating per FEXTOSC bitsCONFIG RSTOSC = HFINT1; HFINTOSC (1MHz);CONFIG RSTOSC = LFINT; LFINTOSC (31kHz);CONFIG RSTOSC = SOSC; SOSC (31kHz);CONFIG RSTOSC = EXT4X; EXTOSC with 4x PLL, with EXTOSC operating per FEXTOSC bits;CONFIG RSTOSC = HFINT32; HFINTOSC with 2x PLL (32MHz); CLKOUTEN: Clock Out Enable bitCONFIG CLKOUTEN = OFF; CLKOUT function is disabled; I/O or oscillator function on OSC2;CONFIG CLKOUTEN = ON; CLKOUT function is enabled; FOSC/4 clock appears at OSC2; CSWEN: Clock Switch Enable bitCONFIG CSWEN = ON; Writing to NOSC and NDIV is allowed;CONFIG CSWEN = OFF; The NOSC and NDIV bits cannot be changed by user software; FCMEN: Fail-Safe Clock Monitor Enable bitCONFIG CSWEN = ON; Fail-Safe Clock Monitor is enabled;CONFIG CSWEN = OFF; Fail-Safe Clock Monitor is disabled; Config bits for register: CONFIG2 @ 0x8008; MCLRE: Master Clear Enable bit;CONFIG MCLRE = ON; MCLR/VPP pin function is MCLR; Weak pull-up enabledCONFIG MCLRE = OFF; MCLR/VPP pin function is digital input; MCLR internally disabled; Weak pull-up under control of port pin's WPU control bit.; PWRTE: Power-up Timer Enable bitCONFIG PWRTE = OFF; PWRT disabled;CONFIG PWRTE = ON; PWRT enabled; WDTE: Watchdog Timer Enable bits;CONFIG WDTE = ON; WDT enabled, SWDTEN is ignored;CONFIG WDTE = SLEEP; WDT enabled while running and disabled in SLEEP/IDLE; SWDTEN is ignoredCONFIG WDTE = SWDTEN; WDT controlled by the SWDTEN bit in the WDTCON register;CONFIG WDTE = OFF; WDT disabled; SWDTEN is ignored; LPBOREN: Low-power BOR enable bitCONFIG LPBOREN = OFF; ULPBOR disabled;CONFIG LPBOREN = ON; ULPBOR enabled; BOREN: Brown-out Reset Enable bitsCONFIG BOREN = ON; Brown-out Reset enabled, SBOREN bit ignored;CONFIG BOREN = SLEEP; Brown-out Reset enabled while running, disabled in Sleep; SBOREN is ignored;CONFIG BOREN = SBOREN; Brown-out Reset enabled according to SBOREN;CONFIG BOREN = OFF; Brown-out Reset disabled; BORV: Brown-out Reset Voltage selection bitCONFIG BORV = LOW; Brown-out voltage (Vbor) set to 2.45V;CONFIG BORV = HIGH; Brown-out voltage (Vbor) set to 2.7V; PPS1WAY: PPSLOCK bit One-Way Set Enable bitCONFIG PPS1WAY = ON; The PPSLOCK bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle;CONFIG PPS1WAY = OFF; The PPSLOCK bit can be set and cleared repeatedly (subject to the unlock sequence); STVREN: Stack Overflow/Underflow Reset Enable bitCONFIG STVREN = ON; Stack Overflow or Underflow will cause a Reset;CONFIG STVREN = OFF; Stack Overflow or Underflow will not cause a Reset; DEBUG: Debugger enable bitCONFIG DEBUG = OFF; Background debugger disabled;CONFIG DEBUG = ON; Background debugger enabled; Config bits for register: CONFIG3 @ 0x8009; WRT: User NVM self-write protection bits;CONFIG WRT = OFF; Write protection off;CONFIG WRT = BOOT; 0000h to 01FFh write-protected, 0200h to 3FFFh may be modified;CONFIG WRT = HALF; 0000h to 1FFFh write-protected, 2000h to 3FFFh may be modifiedCONFIG WRT = ALL; 0000h to 3FFFh write protected, no addresses may be modified; LVP: Low Voltage Programming Enable bit;CONFIG LVP = ON; Low Voltage programming enabled. MCLR/VPP pin function is MCLR. MCLRE configuration bit is ignored.CONFIG LVP = OFF; High Voltage on MCLR/VPP must be used for programming.; Config bits for register: CONFIG4 @ 0x800A; CP: User NVM Program Memory Code Protection bitCONFIG CP = OFF; User NVM code protection disabled;CONFIG CP = ON; User NVM code protection enabled; CPD: Data NVM Memory Code Protection bitCONFIG CPD = OFF; Data NVM code protection disabled;CONFIG CPD = ON; Data NVM code protection enabled; Register: IDLOC0 @ 0x8000;CONFIG IDLOC0 = 0x55; Register: IDLOC1 @ 0x8001;CONFIG IDLOC1 = 0xAA; Register: IDLOC2 @ 0x8002;CONFIG IDLOC2 = 0x55; Register: IDLOC3 @ 0x8003;CONFIG IDLOC3 = 0xAA; Place includes after device configuration to avoid label clashes.; An example of such is "SWDTEN", which is both a configuration option and; the name of a device register.#include <xc.inc>; ********** Common RAM working registers **********; MainAREG EQU 0x0070BREG EQU 0x0071CREG EQU 0x0072DREG EQU 0x0073LREG EQU 0x0074HREG EQU 0x0075TEMP EQU 0x0076TEMP1 EQU 0x0077TEMP0 EQU 0x0076; ISRISR_AREG EQU 0x0078ISR_BREG EQU 0x0079ISR_CREG EQU 0x007AISR_DREG EQU 0x007BISR_LREG EQU 0x007CISR_HREG EQU 0x007DISR_TEMP EQU 0x007EISR_TEMP1 EQU 0x007FISR_TEMP0 EQU 0x007E; ********** General purpose RAM (banked) **********; Bank 0 (0x0020 to 0x006F); Bank 1 (0x00A0 to 0x00EF); Bank 2 (0x0120 to 0x016F); EUSART receiver 8 byte FIFO data structure. Occupies 10 bytes.RX_FIFO EQU 0x0120RX_FIFO_EQ EQU 0x0120RX_FIFO_SQ EQU 0x0121RX_FIFO_00 EQU 0x0122RX_FIFO_01 EQU 0x0123RX_FIFO_02 EQU 0x0124RX_FIFO_03 EQU 0x0125RX_FIFO_04 EQU 0x0126RX_FIFO_05 EQU 0x0127RX_FIFO_06 EQU 0x0128RX_FIFO_07 EQU 0x0129; EUSART transmitter 8 byte FIFO data structure. Occupies 10 bytes.TX_FIFO EQU 0x012ATX_FIFO_EQ EQU 0x012ATX_FIFO_SQ EQU 0x012BTX_FIFO_00 EQU 0x012CTX_FIFO_01 EQU 0x012DTX_FIFO_02 EQU 0x012ETX_FIFO_03 EQU 0x012FTX_FIFO_04 EQU 0x0130TX_FIFO_05 EQU 0x0131TX_FIFO_06 EQU 0x0132TX_FIFO_07 EQU 0x0133; Command buffer 8 byte FIFO data structure. Occupies 10 bytes.CB_FIFO EQU 0x0134CB_FIFO_EQ EQU 0x0134CB_FIFO_SQ EQU 0x0135CB_FIFO_00 EQU 0x0136CB_FIFO_01 EQU 0x0137CB_FIFO_02 EQU 0x0138CB_FIFO_03 EQU 0x0139CB_FIFO_04 EQU 0x013ACB_FIFO_05 EQU 0x013BCB_FIFO_06 EQU 0x013CCB_FIFO_07 EQU 0x013D; Bank 3 (0x01A0 to 0x01EF); ...; Bank 25 (0x0CA0 to 0x0CBF); ********** Constants **********; ********** Reset vector **********PSECT RES_VECT, class = CODE, delta = 2, reloc = 1 ; -Wl,-PRES_VECT=0000hPROG_START:PAGESEL INITGOTO INIT; ********** Interrupt vector **********PSECT INT_VECT, class = CODE, delta = 2, reloc = 1 ; -Wl,-PINT_VECT=0004hISR_START:BANKSEL PIR1; EUSART receiverBTFSC RCIFBRA ISR_EURX; EUSART transmitterBTFSC TXIFBRA ISR_EUTX; Oops! Unhandled interrupt.RESETISR_EURX:; Process inbound dataBANKSEL RC1STA; Discard if framing errorBTFSC FERRBRA EURX_DISCARD; Select RX FIFOMOVLW HIGH( RX_FIFO )MOVWF FSR0HMOVLW LOW( RX_FIFO )MOVWF FSR0L; Check if RX FIFO is fullMOVIW 1 SUBWF INDF0, WXORLW 8; FIFO size; Discard if RX FIFO is fullBTFSC ZEROBRA EURX_DISCARD; Enqueue data into RX FIFOMOVF INDF0, WANDLW 7; FIFO size - 1MOVWF ISR_TEMP0ADDWF FSR0L, FMOVF RC1REG, WMOVWI 2 MOVF ISR_TEMP0, WSUBWF FSR0L, FINCF INDF0, F; DoneRETFIEEURX_DISCARD:; Discard received characterMOVF RC1REG, WRETFIEISR_EUTX:; Process outbound dataBANKSEL TX1REG; Select TX FIFOMOVLW HIGH( TX_FIFO )MOVWF FSR0HMOVLW LOW( TX_FIFO )MOVWF FSR0L; Check if TX FIFO is emptyMOVIW 1 XORWF INDF0, W; If TX FIFO is empty, disable interrupts and returnBTFSC ZEROBRA EUTX_OFF; Dequeue data from TX FIFO and transmitMOVIW ++ FSR0ANDLW 7MOVWF ISR_TEMP0ADDWF FSR0L, FMOVIW 1 MOVWF TX1REGMOVF ISR_TEMP0, WSUBWF FSR0L, FINCF INDF0, F; DoneRETFIEEUTX_OFF:; Switch transmitter interrupts offBANKSEL PIE1BCF TXIERETFIE; ********** Main program **********PSECT MAIN_PROG, class = CODE, delta = 2, reloc = 1INIT:; Oscillator configBANKSEL OSCCON1MOVLW 01100000B; Select HFINTOSC with no dividerMOVWF OSCCON1MOVLW 00000100B; Set HFINTOSC to 8MHzMOVWF OSCFRQ; Port configBANKSEL LATACLRF LATA; Set RA output latches lowBANKSEL TRISABCF TRISA4; Digital output RA4 (EUSART TX)BANKSEL ANSELABCF ANSA4; Switch off analog for RA4 (EUSART TX)BCF ANSA5; Switch off analog for RA5 (EUSART RX); PPS configBANKSEL RXPPSMOVLW 00000101B; Assign EUSART RX input to RA5MOVWF RXPPSBANKSEL RA4PPSMOVLW 00010100B; Assign RA4 to EUSART TXMOVWF RA4PPS; ***** EUSART config *****BANKSEL BAUD1CON;MOVLW 01000000B; Default POR value;MOVWF BAUD1CON; 9600 baud rate async for 8MHz Fosc;BCF SYNC;BCF BRGH;BCF BRG16;MOVLW 12;MOVWF SP1BRGL;CLRF SP1BRGH; 57600 baud rate async for 8MHz Fosc;BCF SYNC;BSF BRGH;BSF BRG16;MOVLW 34;MOVWF SP1BRGL;CLRF SP1BRGH; 115200 baud rate async for 8MHz FoscBCF SYNCBSF BRGHBSF BRG16MOVLW 16MOVWF SP1BRGLCLRF SP1BRGHBSF TXEN; Enable transmitterBSF CREN; Enable receiverBSF SPEN; Enable the serial port; Timer0 configBANKSEL T0CON0;MOVLW 01000100B; Fosc/4, synced, 1:16 prescaler (125KHz with 8MHz Fosc)MOVLW 01000011B; Fosc/4, synced, 1:8 prescaler (250KHz with 8MHz Fosc);MOVLW 01000010B; Fosc/4, synced, 1:4 prescaler (500KHz with 8MHz Fosc)MOVWF T0CON1MOVLW 124; 1:16: 1KHz, 1:8: 2KHz, 1:4: 4KHzMOVWF TMR0HMOVLW 10000000BMOVWF T0CON0; Enable TMR0, no output, 8 bit mode, no postscaler; InterruptsBANKSEL PIE1BSF RCIE; Enable EUSART receiver interruptsBSF PEIE; Enable peripheral interruptsBSF GIE; Enable global interrupts; Initialise registersBANKSEL 0; Initialise FIFOsBANKSEL RX_FIFO; All FIFOs are on the same bankCLRF RX_FIFO_EQCLRF RX_FIFO_SQCLRF TX_FIFO_EQCLRF TX_FIFO_SQCLRF CB_FIFO_EQCLRF CB_FIFO_SQMAIN_LOOP:; Main loopBANKSEL 0; Wait until character is receivedCALL GET_CHAR; Is the character LF or CR?; Parse the command buffer if soMOVF TEMP0, WXORLW 10BTFSC ZEROBRA PARSE_CBMOVF TEMP0, WXORLW 13BTFSC ZEROBRA PARSE_CB; Is the character a DEL (backspace key)?; Update command buffer if so; This is not to be confused with the BS character (8),; which moves the cursor left without deleting the; previous character.MOVF TEMP0, WXORLW 127BTFSC ZEROBRA DEL_CHAR; Is the character printable?; Lower threshold: 32, Upper threshold: 126MOVLW 32; Clear CARRY if value is too smallSUBWF TEMP0, WBTFSC CARRY; If CARRY is clear, skipSUBLW ( 126 - 32 ); Clear CARRY if value is too large; If the character is not printable, do nothing.BTFSS CARRYBRA MAIN_LOOP; Put character onto the command bufferMOVF TEMP0, WCALL CB_ENQ; Is the command buffer full?; Send a BELL character if soMOVLW 7BTFSC ZEROMOVWF TEMP0; Echo characterMOVF TEMP0, WCALL SEND_CHAR; ReturnBRA MAIN_LOOPDEL_CHAR:; Remove last character from command bufferCALL CB_POP; Send BELL character if command buffer was empty.; Else, send DEL character.MOVLW 7BTFSS ZEROMOVLW 127CALL SEND_CHAR; DoneBRA MAIN_LOOPPARSE_CB:; Send CR LFMOVLW 13CALL SEND_CHARMOVLW 10CALL SEND_CHAR; Clear character countCLRF CREG; Echo command buffer contentsPARSE_CB_LOOP:CALL CB_DEQ; Continue if command buffer is emptyBTFSC ZEROBRA PARSE_CB_CONT; Echo command buffer characterMOVF TEMP0, WCALL SEND_CHAR; Increment character count and loop backINCF CREG, FBRA PARSE_CB_LOOPPARSE_CB_CONT:; Send another CR LF if command buffer was not emptyMOVF CREG, FBTFSC ZEROBRA MAIN_LOOP; Send CR LFMOVLW 13CALL SEND_CHARMOVLW 10CALL SEND_CHAR; Clear the command buffer;BANKSEL CB_FIFO;CLRF CB_FIFO_EQ;CLRF CB_FIFO_SQ; DoneBRA MAIN_LOOP; ********** Subroutines **********; Enqueue character in WREG for transmission via EUSART.; If the FIFO is full, wait for room.SEND_CHAR:; Store character to sendMOVWF TEMP0; Select TX FIFOMOVLW HIGH( TX_FIFO )MOVWF FSR0HMOVLW LOW( TX_FIFO )MOVWF FSR0L; Wait for room and enqueueCALL ENQ_WAIT; Enable EUSART TX interruptsMOVF BSR, W; Back up BSRBANKSEL PIE1BSF TXIEMOVWF BSR; Restore BSR; DoneRETURNCB_ENQ:; Store character to enqueueMOVWF TEMP0; Select command buffer FIFOMOVLW HIGH( CB_FIFO )MOVWF FSR0HMOVLW LOW( CB_FIFO )MOVWF FSR0LBRA ENQ_NOWAIT; Enqueue data to FIFOENQ_WAIT:; Wait for roomMOVIW 1 SUBWF INDF0, WXORLW 8; FIFO sizeBTFSC ZEROBRA ENQ_WAITBRA ENQ_INNER; Enqueue data to FIFOENQ_NOWAIT:; Return if FIFO is full. ZERO will be setMOVIW 1 SUBWF INDF0, WXORLW 8; FIFO sizeBTFSC ZERORETURNENQ_INNER:; Enqueue data onto FIFOMOVF INDF0, WANDLW 7; FIFO size - 1MOVWF TEMP1ADDWF FSR0L, FMOVF TEMP0, WMOVWI 2 MOVF TEMP1, WSUBWF FSR0L, FINCF INDF0, F; Done. ZERO will be clearBCF ZERORETLW 0; Dequeue received character from EUSART.; If the FIFO is empty, wait for received character.GET_CHAR:; Select RX FIFOMOVLW HIGH( RX_FIFO )MOVWF FSR0HMOVLW LOW( RX_FIFO )MOVWF FSR0LBRA DEQ_WAIT; Dequeue character from command bufferCB_DEQ:; Select command buffer FIFOMOVLW HIGH( CB_FIFO )MOVWF FSR0HMOVLW LOW( CB_FIFO )MOVWF FSR0LBRA DEQ_NOWAIT; Dequeue data from FIFODEQ_WAIT:; Wait for dataMOVIW 1 XORWF INDF0, WBTFSC ZEROBRA DEQ_WAITBRA DEQ_INNER; Dequeue data from FIFODEQ_NOWAIT:; Do nothing if FIFO is empty. ZERO will be set.MOVIW 1 XORWF INDF0, WBTFSC ZERORETURNDEQ_INNER:; Dequeue data from FIFOMOVIW ++ FSR0ANDLW 7; FIFO size - 1MOVWF TEMP1ADDWF FSR0L, FMOVIW 1 MOVWF TEMP0MOVF TEMP1, WSUBWF FSR0L, FINCF INDF0, FADDFSR FSR0, -1; Done. ZERO will be clear.BCF ZERORETLW 0; Remove character from end of command bufferCB_POP:; Select command buffer FIFOMOVLW HIGH( CB_FIFO )MOVWF FSR0HMOVLW LOW( CB_FIFO )MOVWF FSR0LBRA POP_NOWAIT; Remove data from end of FIFO; Wait for dataPOP_WAIT:MOVIW 1 XORWF INDF0, WBTFSC ZEROBRA POP_WAITBRA POP_INNER; Remove data from end of FIFO; Do nothing if FIFO is empty. ZERO will be set.POP_NOWAIT:MOVIW 1 XORWF INDF0, WBTFSC ZERORETURNPOP_INNER:; Remove data from end of FIFODECF INDF0, WANDLW 7; FIFO size - 1MOVWF TEMP1ADDWF FSR0L, FMOVIW 2 MOVWF TEMP0MOVF TEMP1, WSUBWF FSR0L, FDECF INDF0, F; Done. ZERO will be clearBCF ZERORETLW 0; Return the ASCII hexadecimal character; for the least / most significant nibble in WREG.BIN2HEX_H:SWAPF WREG, WBIN2HEX_L:ANDLW 00001111BBRWRETLW '0'RETLW '1'RETLW '2'RETLW '3'RETLW '4'RETLW '5'RETLW '6'RETLW '7'RETLW '8'RETLW '9'RETLW 'A'RETLW 'B'RETLW 'C'RETLW 'D'RETLW 'E'RETLW 'F'END PROG_START

author: oPossum
author_rank: Super Contributor
timestamp: August 20, 2020, 02:21:52 pm
content: Here are a few of my projects that are in assembly language and use UART (hardware or bit-bang), IIC and have a simple menu system.http://www.compendiumarcana.com/eprom/http://www.compendiumarcana.com/jp1epa/http://www.compendiumarcana.com/caliper/

author: PerranOak
author_rank: Frequent Contributor
timestamp: August 20, 2020, 02:40:02 pm
content: Brill, cheers both.MPASM is no more!?

author: oPossum
author_rank: Super Contributor
timestamp: August 20, 2020, 02:45:07 pm
content: It is still available in MPLAB X. Old asm code will usually require a few tweaks to assemble.Edit: Available in 5.35 and earlier. Replaced with pic-as in 5.40

author: PerranOak
author_rank: Frequent Contributor
timestamp: August 20, 2020, 02:51:11 pm
content: So how do you use assembly now if not MPASM?

author: oPossum
author_rank: Super Contributor
timestamp: August 20, 2020, 02:51:56 pm
content: Older version of MPLAB are also available if you want to use old code as-is or need support for older programming/debugging hardware.https://www.microchip.com/development-tools/pic-and-dspic-downloads-archive

author: Dabbot
author_rank: Regular Contributor
timestamp: August 20, 2020, 02:56:44 pm
content: Quote from: oPossum on August 20, 2020, 02:45:07 pmMPLAB X 5.35 is the last version MPASM is present in.https://www.microchip.com/forums/m1140119.aspx

author: PerranOak
author_rank: Frequent Contributor
timestamp: August 20, 2020, 03:08:55 pm
content: I'm being thick.Does this mean there is no more assembly programming in MPLAB current versions?

author: Dabbot
author_rank: Regular Contributor
timestamp: August 20, 2020, 03:13:34 pm
content: Quote from: PerranOak on August 20, 2020, 03:08:55 pmWhich version are you running?The current version released by Microchip as of this post, MPLAB X IDE v5.40, is the only version without MPASM. If you're using any prior version you're fine.

author: NorthGuy
author_rank: Super Contributor
timestamp: August 20, 2020, 03:54:01 pm
content: Quote from: PerranOak on August 20, 2020, 01:45:49 pmThen I would suggest leaving USB alone.Instead, try to establish communications between two PICs (or between different pins of the same PIC).Start from the simplest - UART. Read how it works. Understand the principles. It is not that much to it. For example:https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitterThen test your understanding - how many wires do you need, how to connect them, what else do you need to establish the communications.Then do the wiring and try communicating. Bit bang the transmitter. If you have a scope or LA, look at the signal you produce. Is it correct?etc.If it takes long time, it's good. Learning needs time. There's no way around this.

author: PerranOak
author_rank: Frequent Contributor
timestamp: August 20, 2020, 04:25:11 pm
content: Cheers NorthGuy. Looks like I’ll have to bite the bullet!With MPASM though, I don’t want to write code that I can’t use in the future. Is there no alternative but to use old MPLABs?

author: NorthGuy
author_rank: Super Contributor
timestamp: August 20, 2020, 06:33:15 pm
content: Quote from: PerranOak on August 20, 2020, 04:25:11 pmThey have new asm, which is somewhat worse than MPASM, but should be still Ok for your purposes. It might be easier to use C instead of asm. Your goal is to learn the principles, not to create super efficient programs.You cannot learn and write code which you're going to use for your entire life at the same time. In the best case, five years from now you'll be ashamed of the code you wrote now (which means you have learnt something). In the worst case, you get addicted to the code you write now and will be living in the past for your entire life.

author: 3dgeo
author_rank: Frequent Contributor
timestamp: August 20, 2020, 07:14:56 pm
content: I'll share my path to mastering serial com:I wanted too to send data between PC and MCU, my chosen PC software for that is Processing (I would prefer VS C# to be honest and I will migrate to VS at some point cuz it's way more useful to learn VS in the long run). Stay with C#, there are very good videos on making coms with Arduino and VS.First you have to create your own "protocol", that is create data packet structure so your code on MCU and PC could recognise data and do specific things with it – it sounds way complicated than actually is... I "rip off" bootloader communication structure (don't know if it's best but I'm getting what I want). Till now I was able to make it work pretty well.My advice would be to pick a specific project and just go with it, you will learn everything you need a long the way.First my protocol example achievement was time from PC on the screen, with 2nd iteration I've tried small image transfer to MCU:And the latest "upgrade" is real time sound equiliser send from PC:Hopefully this will give you some ideas and inspiration, I would strongly recommend starting with simple OLED display too.I should mention that if you are intimidated by PC software side you can completely skip it by using 2 MCUs that communicate to each other, this way you only have to create one code for both MCUs.

author: Ian.M
author_rank: Super Contributor
timestamp: August 20, 2020, 08:18:47 pm
content: Its preferable to stick with an ASCII more or less human readable protocol so you can test the PC end with a terminal. Using two identical MCUs you got to get both RX and TX working properly to transfer any data and unless you carefully scope it, ypu'll have no idea if the baud rate is out of spec.

author: 3dgeo
author_rank: Frequent Contributor
timestamp: August 20, 2020, 10:27:40 pm
content: Quote from: Ian.M on August 20, 2020, 08:18:47 pmI can't disagree more – ASCII gives you not all 255 "visible" symbols, especially if something went wrong. Hex on the other hand will always return visible understandable value. Getting RX and TX working I think is one of the the goal here, and there are no need to "carefully" scope it – I'm sure there are prebuilt libs for basic serial functionality (sent/received data) where author can begin building his own protocol with, and usually you set your baud rate when you initialise serial – I can't imagine being some inconsistencies if rates are set equally on both ends, especially in development conditions where there shouldn't be any interference that may occur in "real world" situations. I actually tried to break serial when I was creating mine – still working even at 250000.

author: Zikomorocco
author_rank: Newbie
timestamp: August 21, 2020, 03:51:35 am
content: You can use "Pandas" and "Serial" in Python to receive any serial data from a microcontroller and store it in Excel if you want.

author: Dabbot
author_rank: Regular Contributor
timestamp: August 21, 2020, 04:27:09 am
content: Quote from: PerranOak on August 20, 2020, 04:25:11 pmDon't stress! It's still widely in use, as are a lot of the older MPLAB releases.Get yourself a copy of MPLAB X v5.30 from the downloads archive and dive in:https://www.microchip.com/development-tools/pic-and-dspic-downloads-archive