Skip to content

Commit

Permalink
Add samples about SERCOM as USART
Browse files Browse the repository at this point in the history
  • Loading branch information
TK-A369 committed Jan 11, 2021
1 parent 1af345a commit b44a5bd
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 0 deletions.
105 changes: 105 additions & 0 deletions sercom-usart/samd21sercom.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "sam.h"
#include "samd21sercom.h"

void SAMD21SercomUsart::init(char sercomNum, char clkGen, SAMD21SercomUsartConfig_t *_config)
{
config = _config;
char sercomPmMask = 0;
char sercomClk = 0;
IRQn_Type sercom_irqn = (IRQn_Type)0;
sercom = (Sercom *)0;
switch(sercomNum) //Select correct SERCOM
{
case 0:
sercomPmMask = PM_APBCMASK_SERCOM0;
sercomClk = GCLK_CLKCTRL_ID_SERCOM0_CORE;
sercom_irqn = SERCOM0_IRQn;
sercom = SERCOM0;
break;
case 1:
sercomPmMask = PM_APBCMASK_SERCOM1;
sercomClk = GCLK_CLKCTRL_ID_SERCOM1_CORE;
sercom_irqn = SERCOM1_IRQn;
sercom = SERCOM1;
break;
case 2:
sercomPmMask = PM_APBCMASK_SERCOM2;
sercomClk = GCLK_CLKCTRL_ID_SERCOM2_CORE;
sercom_irqn = SERCOM2_IRQn;
sercom = SERCOM2;
break;
case 3:
sercomPmMask = PM_APBCMASK_SERCOM3;
sercomClk = GCLK_CLKCTRL_ID_SERCOM3_CORE;
sercom_irqn = SERCOM3_IRQn;
sercom = SERCOM3;
break;
case 4:
sercomPmMask = PM_APBCMASK_SERCOM4;
sercomClk = GCLK_CLKCTRL_ID_SERCOM4_CORE;
sercom_irqn = SERCOM4_IRQn;
sercom = SERCOM4;
break;
case 5:
sercomPmMask = PM_APBCMASK_SERCOM5;
sercomClk = GCLK_CLKCTRL_ID_SERCOM5_CORE;
sercom_irqn = SERCOM5_IRQn;
sercom = SERCOM5;
break;
}
PM->APBCMASK.reg |= sercomPmMask; //Deliver clock to SERCOM
GCLK->CLKCTRL.reg = sercomClk //Clock for correct SERCOM
| (clkGen << GCLK_CLKCTRL_GEN_Pos) //Use correct GCLK Generator
| GCLK_CLKCTRL_CLKEN; //Enable clock
sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE_USART_INT_CLK //USART with internal clock
| (config->sampleRate << SERCOM_USART_CTRLA_SAMPR_Pos) //Given sample rate
| (config->txPos << SERCOM_USART_CTRLA_TXPO_Pos) //Given TX position
| (config->rxPo << SERCOM_USART_CTRLA_RXPO_Pos) //Given RX position
| (0 << SERCOM_USART_CTRLA_SAMPA_Pos) //Middle sample adjustment
| (config->comMode << SERCOM_USART_CTRLA_CMODE_Pos) //Given communication mode
| (config->dataOrder << SERCOM_USART_CTRLA_DORD_Pos); //Given data order
sercom->USART.CTRLB.reg = (config->txEn ? SERCOM_USART_CTRLB_TXEN : 0) //Enable or disable TX
| (config->rxEn ? SERCOM_USART_CTRLB_RXEN : 0); //Enable or disable RX
sercom->USART.BAUD.reg = config->baud; //Given baud rate
sercom->USART.INTENSET.reg = (config->intRxComplete ? SERCOM_USART_INTENSET_RXC : 0);//Enable or disable receive complete interrupt
sercom->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; //Enable SERCOM

if(config->intRxComplete) NVIC_EnableIRQ(sercom_irqn); //Enable or not SERCOM interrupt
}

void SAMD21SercomUsart::send(char data)
{
while(!(sercom->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_DRE)); //Wait for data buffer
sercom->USART.DATA.reg = data; //Send
}

void SAMD21SercomUsart::sendStr(char *str)
{
while(*str != 0) //If pointed char is not 0
{
send(*str); //Send pointed char
str++; //Move pointer forward
}
}

char SAMD21SercomUsart::available(void)
{
if(sercom->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_RXC) //If there are received data
{
return 1;
}
else
{
return 0;
}
}

char SAMD21SercomUsart::read(void)
{
char data = 0;
if(available()) //If data has been received
{
data = sercom->USART.DATA.reg; //Read received data
}
return data;
}
49 changes: 49 additions & 0 deletions sercom-usart/samd21sercom.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef SAMD21SERCOM_H
#define SAMD21SERCOM_H

#include "sam.h"

typedef struct SAMD21SercomUsartConfig
{
char sampleRate;
char txPos;
char rxPo;
char format;
char comMode;
char dataOrder;
char charSize;
char stopBits;
char parityMode;
char txEn;
char rxEn;
int baud;
char intRxComplete;
} SAMD21SercomUsartConfig_t;

class SAMD21SercomUsart
{
public:
//Configuration of USART
SAMD21SercomUsartConfig *config;

//Initializing function
//Note: this configures clock delivery, but user must configure I/O pins!
void init(char sercomNum, char clkGen, SAMD21SercomUsartConfig_t *_config);

//Send data
void send(char data);

//Send string
//String must have 0 at end
void sendStr(char *str);

//This function checks is there are received data
char available(void);

//Read received data
char read(void);
private:
Sercom *sercom;
};

#endif

0 comments on commit b44a5bd

Please sign in to comment.