Code Example of LEB Blinking and UART Communication for dsPIC30F4013
Tags: c, pic, embed, uart
Published: 2022-05-22 01:31:19

dsPIC series are famous for embedded system development. However, it is difficult for me to use dsPIC30F4013 to blink LED and communicate with the PC through the UART (Universal Asynchronous Receiver/Transmitter) communication.
I share the sample code of LED Blinking and UART communication for dsPIC30F4013.
This code works with the internal clock.
It blinks LED at 1Hz intervals and transfers "S" through the UART communication.

# Circuit
## Photo (Breadboard Prototyping)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mmkln448z929dt2pwz7u.jpg)

## Wiring Table
|dsPIC30F4013|Peripheral Devices (LED or [FT232](https://media.digikey.com/pdf/Data%20Sheets/Sparkfun%20PDFs/BOB-13263_Web.pdf))|
|------------|---------------------------------|
|Vdd|3V3(FT232)|
|Vss|GND(FT232)|
|pin25(U1TX)|RXD(FT232)|
|pin26(U1RX)|TXD(FT232)|
|pin27|Anode(LED)|

# Source Code

```c
// FOSC
#pragma config FOSFPR = FRC_PLL4             // Oscillator (Internal Fast RC (No change to Primary Osc Mode bits))
#pragma config FCKSMEN = CSW_FSCM_OFF   // Clock Switching and Monitor (Sw Disabled, Mon Disabled)

// FWDT
#pragma config FWPSB = WDTPSB_16        // WDT Prescaler B (1:16)
#pragma config FWPSA = WDTPSA_512       // WDT Prescaler A (1:512)
#pragma config WDT = WDT_OFF            // Watchdog Timer (Disabled)

// FBORPOR
#pragma config FPWRT = PWRT_64          // POR Timer Value (64ms)
#pragma config BODENV = BORV27          // Brown Out Voltage (2.7V)
#pragma config BOREN = PBOR_ON          // PBOR Enable (Enabled)
#pragma config MCLRE = MCLR_DIS          // Master Clear Enable (Enabled)

// FGS
#pragma config GWRP = GWRP_OFF          // General Code Segment Write Protect (Disabled)
#pragma config GCP = CODE_PROT_OFF      // General Segment Code Protection (Disabled)

// FICD
#pragma config ICS = ICS_PGD            // Comm Channel Select (Use PGC/EMUC and PGD/EMUD)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

unsigned int counter = 0;   // Initialize counter

int main() {
    /* OSCCON oscillator setting register */
    OSCCONbits.CF = 0;  // Not detected clock failure
    OSCCONbits.COSC = 0b111;    // PLL oscillator which was defined FOSFPR
    OSCCONbits.LOCK = 1;    // PLL is in lock
    OSCCONbits.LPOSCEN = 0; // Secondary oscillator is disabled
    OSCCONbits.NOSC = 0b111;    // New PLL oscillator which was defined
    OSCCONbits.OSWEN =  0;  // Switch is completed
    OSCCONbits.POST = 0;    // Postscaler does not alter clock
    
    /* IO Setting */
    TRISA = 0;  // Digital out
    TRISB = 0;  // Digital out
    TRISC = 0;  // Digital out
    TRISD = 0;  // Digital out
    TRISF = 0;  // Digital out
    TRISFbits.TRISF2 = 1;   // RX pin setting
    TRISFbits.TRISF3 = 0;   // TX pin setting
    TRISBbits.TRISB0 = 1;   // Analog in
    TRISBbits.TRISB1 = 1;   // Analog in
    TRISBbits.TRISB2 = 1;   // Analog in
    TRISBbits.TRISB3 = 1;   // Analog in
    TRISBbits.TRISB4 = 1;   // Analog in
    TRISBbits.TRISB5 = 1;   // Analog in
    TRISBbits.TRISB8 = 1;   // Analog in
    TRISBbits.TRISB9 = 1;   // Analog in
    TRISBbits.TRISB10 = 1;  // Analog in
    TRISBbits.TRISB11 = 1;  // Analog in
    TRISBbits.TRISB12 = 1;  // Analog in
    
   /*Timer Setting Register(ADC Sampling Time Management)*/
    T1CONbits.TON = 0; //Timer OFF. タイマーOFF.
    T1CONbits.TCS = 0; //Use internal Clock. 内部クロックを使用.
    T1CONbits.TGATE = 0; //Gate time accumulate is off.ゲートタイム累積無効. 
    T1CONbits.TSIDL = 0; //Continue on IDLE mode. アイドルモードでタイマ継続.
    T1CONbits.TSYNC = 0; //NONE. 無視(TCS = 0のとき)
    T1CONbits.TCKPS = 0b11; //prescaler 256
    
    /*Interrupt Setting*/
    PR1 = 28; //700Hz
    IPC0bits.T1IP = 5; //Interrupt priority is 5. 優先順位5, 高いほうが優先順位が高い.
    IEC0bits.T1IE = 1; //Timer 1 interrupt is enable. タイマ1割り込みON.
    IFS0bits.T1IF = 0; //Timer 1 Interrupt flag is off. タイマ1割り込みフラグ0。
    T1CONbits.TON = 1; //Timer ON
    
    /* UART Setting */ 
    U1MODEbits.UARTEN = 1; //UART disabled
    U1MODEbits.USIDL = 0; //Run UART on IDLE mode
    U1MODEbits.ALTIO = 0; //Alternate pin is enabled
    U1MODEbits.WAKE = 0; //Wakeup is disabled
    U1MODEbits.LPBACK = 0; //Loopback mode is disabled
    U1MODEbits.ABAUD = 1; //U1RX to Capture
    U1MODEbits.PDSEL = 0; //No parity 8-bit
    U1MODEbits.STSEL = 0; //1STOP bit
    U1STAbits.UTXISEL = 1; //When buffer is empty
    U1STAbits.UTXBRK = 0; //Transfer break is normal mode
    U1STAbits.URXISEL = 0b00; //When accepting any character, interrupt is occured
    U1STAbits.ADDEN = 0; //Address detector is disabled
    U1STAbits.OERR = 0; //Not Overrun (First write only)
    
    U1BRG = 49;
    U1MODEbits.UARTEN = 1; //UART disabled
    U1STAbits.UTXEN = 1; //UART TX is enabled.
    
    PORTFbits.RF5 = 1;   // Invert bit
    while(1);
}

int flagLED = 0;
int counterLED  = 0;
void __attribute__((interrupt, shadow, auto_psv)) _T1Interrupt(void) {
    IFS0bits.T1IF = 0;  // Flag is low
    counterLED++;
    if(counterLED >= 1000) {
        printf("S\n");
        if (flagLED == 0) flagLED = 1;
        else flagLED = 0;
        PORTFbits.RF5 = flagLED;
        counterLED = 0;
    }
}
```

# Demo
{% embed https://youtu.be/agoB07lBCxE %}
{% embed https://youtu.be/mFhUKO3ZInY %}

-----
This original article is the following that is written by me. This article was translated from Japanese to English.
{% embed https://zenn.dev/akira_kashihara/articles/a28442d4425e8d %}