Arduino Uno - Arduino M0(SAMD21G) serial 통신
참고: https://learn.adafruit.com/using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports/creating-a-new-serial
참고: https://learn.adafruit.com/using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports/muxing-it-up
*Uno
rx pin - D2
tx pin - D3
코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #include <SoftwareSerial.h> SoftwareSerial ser(2,3); void setup() { // put your setup code here, to run once: Serial.begin(9600); ser.begin(9600); Serial.println("hi im uno"); } void loop() { ser.write('c'); while(ser.available() > 0){ char temp = ser.read(); Serial.println(temp); } delay(1000); } | cs |
*M0(SAMD21G)
rx pin - 30(PB03)
tx pin - A5(PB02)
코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | #include <Arduino.h> #include "wiring_private.h" #include <LiquidCrystal_I2C.h> Uart SerialX(&sercom5, 30, A5, SERCOM_RX_PAD_1, UART_TX_PAD_0); // rx, tx LiquidCrystal_I2C lcd(0x38, 20, 4); void SERCOM5_Handler(){ // SerialUSB.println("irq"); SerialX.IrqHandler(); } void setup() { lcd.init(); lcd.backlight(); lcd.clear(); SerialUSB.begin(9600); SerialX.begin(9600); pinPeripheral(30, PIO_SERCOM_ALT); pinPeripheral(A5, PIO_SERCOM_ALT); SerialUSB.println("hi im m0_serialUSB"); lcd.setCursor(0,0); lcd.print("hi"); } uint8_t i = 0; void loop() { // SerialUSB.println(i); SerialX.write('a'); // delay(5); while(SerialX.available()){ // SerialUSB.print(" - > 0x"); lcd.setCursor(0,0); char temp = SerialX.read(); lcd.print(temp); SerialUSB.println(temp); } delay(1000); } | cs |
SerialX라는 이름의 Uart객체를 생성한다. sercom은 5를 사용한다.
Arduino M0(SAMD21G)는 총 6개의 sercom을 가지고 있으며 chip(SAMD21G)만 따로 떼어내서 사용하는 것이 아니라면 각각의 sercom은 용도에 맞게 예약되어 있다.
sercomN의 각각의 자주쓰는(chip만 떼어서 쓴다고하면 다른용도로도 사용할 수 있다는 것을 명심) 용도는 다음과 같다.
출처: https://forum.arduino.cc/index.php?topic=341054.0 에서 MartinL의 글
참고: variant.cpp
참고: variant.h
sercom0 - Uart Serial (variant.cpp (링크)에서 Serial1 그리고 Serial5으로 선언이 되어있다.)
sercom1 - Uart Serial
sercom2 - Uart Serial
sercom3 - I2C Wire
sercom4 - SPI
sercom5 - EDGB (variant.cpp (링크)에서 Serial로 선언이 되어있다.
M0에서 uart serial 생성에서 기억해야 할 코드는 다음과 같다.
Uart SerialX(&sercom5, 30, A5, SERCOM_RX_PAD_1, UART_TX_PAD_0);
void SERCOM5_Handler(){
SerialX.IrqHandler();
}
SerialX.begin(9600);
pinPeripheral(30, PIO_SERCOM_ALT);
pinPeripheral(A5, PIO_SERCPM_ALT);
각각 설명을 해주면
------------------------------------------------------------------------------------------------------------------------
Uart SerialX(&sercom5, 30, A5, SERCOM_RX_PAD_1, UART_TX_PAD_0);
SerialX라는 이름의 serial 핸들링 객체를 하나 만든다.
파라미터는
Serial( sercomN의 주소값, RX pin number, TX pin number, RX_PAD number, TX_PAD number)
로 구성되어있다.
나는 sercom5를 사용했다.
sercom은 runtime시에 하나만 사용할 수 있다.
------------------------------------------------------------------------------------------------------------------------
RX는 현재 PB03를 사용하고 있다.
TX는 현재 PB02을 사용하고 있다.
windows의 경우
C:\Users\user\AppData\Local\arduino15\packages\arduino\hardware\samd\1.6.20\variants\arduino_mzero
경로에서 variant.cpp를 보면 코드에서 사용할 수 있는 pin 번호가 적혀 있다.


위의 캡처한 사진을 보면
PB03는 30번 핀을 사용하고 있고
PB02은 A5번 핀을 사용하고 있다.
따라서 2번째 3번째 파라미터는
30, A5이 되는 것이다.
Uart SerialX(&sercom5, 30, A5, SERCOM_RX_PAD_1, UART_TX_PAD_0);
------------------------------------------------------------------------------------------------------------------------
3번째 4번째 파라미터는
PAD인데 정확한 의미와 뜻은 잘모른다. mux로 되어있다는 것만 알 수 있다.
그러나 어떻게 사용해야하는지는 알겠다.
SERCOM_RX_PAD_N 형태로 RX_PAD를 설정하고
UART_TX_PAD_N 형태로 TX_PAD 형태로 설정한다.
위의 사진과 SAMD21G의 datasheet(링크)의 23페이지를 살펴보면
PB02과 PB03을 사용하려면 sercom5와 PAD[0] PAD[1]을 사용해야한다.
PB02를 sercom5를 이용해 사용하려면 PAD[0]를 사용해야 한다는 것을 유추할 수 있다.
PB03은 datasheet에서 PAD[1]을 사용하라고 나와있다.

Uart SerialX(&sercom5, 30, A5, SERCOM_RX_PAD_1, UART_TX_PAD_0);
------------------------------------------------------------------------------------------------------------------------
void SERCOM5_Handler(){
SerialX.IrqHandler();
}
는 SerialX의 핸들러를 가져오겟다는 뜻이다. sercom을 사용하기 위해서는 반드시 정의해줘야한다. 함수명이 SERCOMN_Handler 형태로 되어있는 것에 주목하도록하자 우리는 sercom5를 쓰기때문에 SERCOMN_Handler에서 N에 5가 들어갔다.
이 함수는 콜백메소드이다.
------------------------------------------------------------------------------------------------------------------------
SerialX.begin(9600);
따로 설명하지 않겠다.
------------------------------------------------------------------------------------------------------------------------
pinPeripheral(30, PIO_SERCOM_ALT);
pinPeripheral(A5, PIO_SERCPM_ALT);
아까 선택했던 rx pin과 tx pin을 사용해줘야 한다.
pinPeripheral함수를 이용한다.
30번 핀을 PIO_SERCOM_ALT로 사용하겠다는 의미이다.
아까 데이터시트를 보면 D항목의 SERCOM5-ALT항목의
위의 데이터시트 캡처화면의 PB03와 PB02에서 SERCOM5/PAD[0] 열따라 쭉 올라가보면 SERCOM5-ALT가 보인다.
pinPeripheral의 두번째 파라미터는
PAD가 ALT인지 아닌지에 따라 달라질 수 있다.
여기서는 ALT이므로 PIO_SERCOM_ALT 를 사용한다.
ALT가 아닐 시에는 PIO_SERCOM을 사용한다.
------------------------------------------------------------------------------------------------------------------------
*결과
M0 serial monitor

Uno serial monitor
