
Direct Memory Access on PIC MCUs [Part 1]:
This is part 1 of 2 of an example showing how to set up Direct Memory Access (DMA) using the Microchip Code Configurator (MCC) on the PIC18F57Q43 Curiosity Nano to transfer an Analog to Digital (ADC) conversion to a UART TX buffer with zero lines of code and zero CPU utilization using DMA.

Part 2 covers how to set up the second device that will similarly utilize DMA to transfer the contents of the received message in the UART RX buffer to a PWM module that will vary the brightness of the LED.
Table of Contents
This example is extendable to the entire PIC18F Q43 family, as well as other 8-bit PIC devices with the DMA feature (ex. PIC18F K42).
The Timer (TMR0), Analog to Digital Converter with Computation (ADCC), and Universal Asynchronous Receiver Transmitter (UART3) and DMA on-chip peripherals are all used in this project (part1).
This example is covered in video form here --LINK--.
Related Documentation
Software Used
All software used in this example is listed here:
- MPLAB® X IDE 5.30 or newer - link
- MPLAB® XC8 2.10 or a newer compiler - link
- MPLAB® Code Configurator (MCC) 3.95.0 or newer - link
- MPLAB® Code Configurator (MCC) Device Libraries PIC10 / PIC12 / PIC16 / PIC18 MCUs - link
- Microchip PIC18F-Q Series Device Support (1.4.109) or newer - link
Hardware Used
- PIC18F47Q10 Curiosity Nano (DM164150)
- NOTE: There is second one used in part 2 --LINK--
- Potentiometer (x1)
- [Optional] Curiosity Nano Base for Click boards™ (AC164162) - this was only used in lieu of a breadboard.
Setup
The hardware is setup as shown more closely in this video --LINK--. Below is a diagram where of the specific pins I used. You'll notice the Curiosity Nano Baseboard for clicks is missing from this diagram as they were really only used as breadboard-alternatives in this case.

Potentiometer |
Q43 (part 1) |
|
Q43 (part 2) |
+ |
3.3V |
|
|
gnd |
gnd |
|
|
output |
RA0 |
(Yellow Wire) |
|
|
RA3 (UART3 TX) |
-----------> |
RA4 (UART3 RX) |
Operation

Summary
As noted before - this is part 1 of 2 of an example showing how to set up Direct Memory Access (DMA) using the Microchip Code Configurator (MCC) on the PIC18F57Q43 Curiosity Nano to transfer an Analog to Digital (ADC) conversion to a UART TX buffer with zero lines of code and zero CPU utilization using DMA.
More generally, the technique detailed below shows the process of how one can:
- Use the DMA GUI provided in MCC
- Use the DMA to transfer memory from one special function register (SFR) to another SFR
- Specify hardware triggers that will initiate the above memory transfer
The goal here is to exemplify the usage of the GUI provided by MCC that will generate all the code we need. This means that any device that has the DMA peripheral and is supported in MCC can be similarly configured through the same methods. The section below details how to do this.
Walkthrough
Create New MPLAB X Project and Open MCC
- Open the MPLAB X IDE
- Create new project by clicking the icon:
- Alternatively: file >> New Project
- In Choose Project window
- Select Microchip Embedded category
- Select Standalone Project
- Hit Next>
- In Select Device window
- Select PIC18F57Q43 as your device
- Pro-tip: quickly filter for devices by inputting last 3-4 characters of the device and selecting from the drop-down list (e.g. Q43).
- Hit Next>
- In Select Tool (Optional) window
- If device is connected – select Microchip Kits -> PIC18F57Q43 Curiosity Nano (PKOB nano)
- If not, you can do this later when programming the device.
- Hit Next>
- In Select Compiler window
- Select XC8 (v2.10)
- Hit Finish
- Open MCC by clicking the icon in the toolbar

Configure MCC
- In System Module window
- Set Oscillator Select to HFINTOSC

- Under Device Resources in left-hand pane
- Open the Peripherals drop-down
- Double-click the (PIC10/PIC12/…) instance of the ADCC [PIC10/…], TMR0 and UART3 peripherals to add them your project.

- In TMR0 window/tab
- Select FOSC/4 for Clock Source
- Set Clock pre-scaler to 1:64
- Set Requested Period to 50 ms
- What we just did – configured the TMR0 to overflow every ~50ms. You can mess around with the clock source, system clock, and post/pre-scalars to change the % error or the range of acceptable inputs to for the timer period.

- In ADCC window/tab
- Set Clock Source to FRC
- Set Auto-Conversion Trigger to TMR0
- What we just did – changed the clock source to the internal ADC RC oscillator circuit (i.e. FRC), and set up the ADC to get a conversion every time a rising edge is detected from TMR0.

- In the UART window/tab
- Set Baud Rate to 9600

- In the Pin Manager: Grid View window
- UART3 TX3 --> A3
- UAR3 RX3 --> A4 (not needed necessarily since we are just transmitting)
- ADCC ANx --> A0

- In the DMA Manager window


Zoomed in pictures and additional table below are included for clarity


|
Module |
Region |
SFR |
VarName |
VarSize |
Address |
Mode |
Message Size |
Start Trigger |
Abort Trigger |
Src |
ADCC |
SFR |
ADRESL |
- |
- |
- |
increment |
2 |
U3TX |
None |
Dst |
UART3 |
SFR |
U3TXB |
- |
- |
- |
unchanged |
1 |
U3TX |
None |
- Enable DMA Channel1
- What we just did:
- ADCC is the source module of the DMA channel
- ADRESL is the SFR region that we want data to be sourced from
- Mode must be incremented so that we can get the value from ADRESH, which is directly above ADRESL according to the SFR Memory Map.
- Message size is basically how many bytes are coming from the source module. The ADC result register is a 16-bit register, so the message size is 2-bytes.
- Similarly, the UART TX Buffer is 1-byte, so we need to indicate that it can only handle one byte at a time. (i.e. message size = 1)
- Set the DMA start trigger to fire every time TX Buffer is empty (U3TXB). At this point you might wonder – why don’t I just set the trigger for every time there is an ADC conversion? You are certainly given the flexibility to do so by setting Start Trigger to AD. I encourage you to try and see what happens.
- Spoiler Alert: In many cases you will find that there is garbage data being transmitted from the UART. The reason for this is that depending on the relative speed of the UART, the DMA might be overwriting the buffer before the bits are shifting out. The DMA has no knowledge of this information, it’s simply a messenger.
- Hit Generate Project and
- Hit Program the device

Conclusion:
You have finished part 1, now you can either check out the results by using a logic analyzer or oscilloscope or go ahead and check out part 2. --LINK--