8ビット非同期モード 8-bit Asynchronous Mode
Usart1ピンの割り付け
送信と受信のピン割り付けの設定。
送信 | 受信 | |
---|---|---|
デフォルトピン | なし | RC7 |
PPS割り付け可能ポート | ポートB,ポートC | ポートB,ポートC |
18F27Q43には5つのUARTがあります。UART3、4は、ポートAに割り付けることができますが、ポートCに割り付けることはできなくなります。
受信のデフォルトは、RC7。
受信、送信ともに、ポートB、ポートCならどこにでも、PPSを使用して割り付け可能。
※PPS:Peripheral Pin Select Module
Usartボーレート
受信ビットのサンプリングレートを決めます。 Foscから分周します。通信速度の4倍と16倍の速度のサンプリングクロックを生成します。整数値にならないので、目標のボーレートの誤差が、3%以内になるようにBRGSを選択します。
BRGS | BRG/UsartMode | Baud Rate の式 |
---|---|---|
1 | High Rate | Fosc/[4*(U1BRG+1)] |
0 | normal Rate | Fosc/[16*(U1BRG+1)] |
今回はシステムクロックFosc=32Mhz Usartのボーレートを115200bpsに設定しています。
誤差3%以内なので、BRGS=0
で設定します。
Usart受信バッファ、Usart送信バッファ
受信バッファは2バイト、送信バッファは1バイト。 受信バッファがオーバーフローした場合、オーバーフローエラーが発生します。今回、オーバーフローエラーは、チェックしていません。
putch関数 機種依存するprintf標準入出力関数を使用する準備
printfは、stdoutに出力するとき、putch関数を使用します。デフォルトでは、putch関数は、関数名だけ与えられていて、中身が記述されていません。機種ごとに送信フラグ名が違ってくるからです。なので、PIC18F27Q43の送信フラグ名に合わせてputch関数の中身を記述する必要があります。
void putch(uint8_t _txData)
{
if(U1ERRIRbits.TXMTIF==High)//シフトレジスタ空?
{
do{
U1TXB=_txData;
while(U1ERRIRbits.TXMTIF==Low);
}while(U1FIFObits.TXBF);//TXバッファ空になるまで送信。
}else{
//error operation
}
}
getch関数 機種依存する関数
putch関数と同様に、getch関数も、受信フラグ名が機種依存しています。18F27Q43に合わせて、関数の中身を実装します。
uint8_t getch(void)
{
while(PIR4bits.U1RXIF==Low);//受信完了
return U1RXB;
}
今回のソースコード
タイマー0でLEDを0.5秒間隔で点滅させ、同時に、カウンター値をパソコンに送信。
Usartで\nを受信したら、受信内容をそのままエコーバックさせています。
<ソースファイル>
Q_peripheral27Q43.h: タイマー、シリアル通信ヘッダーファイル
Q_peripheral27Q43.h: タイマー、シリアル通信ソースファイル
Q_interrupt27Q43.h: 割込み処理ヘッダーファイル
Q_interrupt27Q43.c: 割込み処理ソースファイル
main.c:メイン関数
#ifndef Q_PERIPHERAL27Q43_H
#define Q_PERIPHERAL27Q43_H
#ifdef __cplusplus
extern "C" {
#endif
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#define Low 0
#define High 1
#define _XTAL_FREQ 32000000
#define BAUDRATE 115200
#define SET_SPBRG_DATA (((unsigned int)((_XTAL_FREQ/4)/BAUDRATE))-1)
#define SET_SPBRG_DATA1 (((unsigned int)((_XTAL_FREQ/16)/BAUDRATE))-1)
//USART---------------------------------------
#define RXUSART_BUFFER_SIZE 20
typedef struct
{
uint8_t buf[RXUSART_BUFFER_SIZE];
uint8_t length;
uint8_t completed;
}_rxUsart;
extern _rxUsart rxUsart;
extern uint8_t usartTxData[20];
extern void usartInit(void);
extern void putch(uint8_t);
extern uint8_t getch(void);
//Timer--------------------------------------
typedef struct
{
uint16_t cnt;
bool fg;
}_tm;
extern _tm tm0;
extern void timer0Init(void);
#endif
#endif /* Q_PERIPHERAL27Q43_H */
#include "Q_peripheral27Q43.h"
//*****************************************************//
//USART初期化
//*****************************************************//
_rxUsart rxUsart;
void usartInit(void)
{
//6.PPS--------------------------------------------------
PPSLOCK = 0x55;
PPSLOCK = 0xAA;
PPSLOCKbits.PPSLOCKED = 0;//Unlock.
U1RXPPS=0b010111; //RC7:rx
RC6PPS=0x20; //RC6:tx
TRISC|=0x80; //RC7:input
PPSLOCK = 0x55;
PPSLOCK = 0xAA;
PPSLOCKbits.PPSLOCKED = 1;//lock.
//1.ボーレート設定115200----------------------------------
U1BRG=SET_SPBRG_DATA1;
//2.モード 非同期
U1CON0bits.MODE=0b0000; //Asynchronous 8-bit USART mode
//4.Serial port enabled
U1CON1bits.ON=1;
//5.Transmit is enabled. Recieve enabled.
U1CON0bits.TXEN=1;
U1CON0bits.RXEN=1;
//7.interrupt setting------------------------------------
PIR4bits.U1RXIF=0;
PIE4bits.U1RXIE=1;
}
void putch(uint8_t _txData)
{
if(U1ERRIRbits.TXMTIF==High)//シフトレジスタ空?
{
do{
U1TXB=_txData;
while(U1ERRIRbits.TXMTIF==Low);
}while(U1FIFObits.TXBF);//TXバッファ空になるまで送信。
}else{
//error operation
}
}
uint8_t getch(void)
{
while(PIR4bits.U1RXIF==Low);//受信完了
return U1RXB;
}
//*****************************************************//
//Timer0初期化
//*****************************************************//
_tm tm0;
void timer0Init(void)
{
//Timer0初期化--------------------------------------------------
T0CON1bits.CS=0b010;//クロックソースFosc/4
T0CON1bits.CKPS=0b0011;//プリスケ1:8
T0CON0bits.MD16=1;//16bitsタイマー
T0CON0bits.OUTPS=0b0000;//ポストスケーラ1:1
TMR0H=0xD8;//10ms Fosc=32Mhz
TMR0L=0xF0;//10ms
T0CON0bits.EN=1;
PIE3bits.TMR0IE=1;
PIR3bits.TMR0IF=0;
}
#ifndef Q_INTERRUPT_H
#define Q_INTERRUPT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "Q_peripheral27Q43.h"
extern void __interrupt(irq(IRQ_U1RX)) USART1RX_ISR(void);
extern void __interrupt(irq(IRQ_TMR0)) Timer0_ISR(void);
#ifdef __cplusplus
}
#endif
#endif /* Q_INTERRUPT_H */
#include "Q_interrupt27Q43.h"
//****************割り込み関数***********************//
// USART1割込み
//**************************************************//
void __interrupt(irq(IRQ_U1RX)) USART1RX_ISR(void)
{
uint8_t ch;
PIR4bits.U1RXIF=0;
ch=getch();
rxUsart.buf[rxUsart.length++]=ch;
if(rxUsart.length>RXUSART_BUFFER_SIZE)
{
rxUsart.length=0;
}
if(ch==0x0a)
{
rxUsart.buf[rxUsart.length-2]=0x00;
PIE4bits.U1RXIE=0;
rxUsart.completed=true;
}
}
//****************割り込み関数***********************//
// Timer0割込み
//**************************************************//
void __interrupt(irq(IRQ_TMR0)) Timer0_ISR(void)
{
PIR3bits.TMR0IF=0;
tm0.cnt++;
TMR0L=0xF0;//10ms
if(tm0.cnt==50)
{
tm0.cnt=0;
tm0.fg=true;
T0CON0bits.EN=0;
PIE3bits.TMR0IE=0;
}
}
// PIC18F27Q43 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1
#pragma config FEXTOSC = OFF // External Oscillator Selection (Oscillator not enabled)
#pragma config RSTOSC = HFINTOSC_64MHZ// Reset Oscillator Selection (HFINTOSC with HFFRQ = 64 MHz and CDIV = 1:1)
// CONFIG2
#pragma config CLKOUTEN = OFF // Clock out Enable bit (CLKOUT function is disabled)
#pragma config PR1WAY = OFF // PRLOCKED One-Way Set Enable bit (PRLOCKED bit can be set and cleared repeatedly)
#pragma config CSWEN = ON // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
// CONFIG3
#pragma config MCLRE = EXTMCLR // MCLR Enable bit (If LVP = 0, MCLR pin is MCLR; If LVP = 1, RE3 pin function is MCLR )
#pragma config PWRTS = PWRT_OFF // Power-up timer selection bits (PWRT is disabled)
#pragma config MVECEN = ON // Multi-vector enable bit (Multi-vector enabled, Vector table used for interrupts)
#pragma config IVT1WAY = ON // IVTLOCK bit One-way set enable bit (IVTLOCKED bit can be cleared and set only once)
#pragma config LPBOREN = OFF // Low Power BOR Enable bit (Low-Power BOR disabled)
#pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled , SBOREN bit is ignored)
// CONFIG4
#pragma config BORV = VBOR_1P9 // Brown-out Reset Voltage Selection bits (Brown-out Reset Voltage (VBOR) set to 1.9V)
#pragma config ZCD = OFF // ZCD Disable bit (ZCD module is disabled. ZCD can be enabled by setting the ZCDSEN bit of ZCDCON)
#pragma config PPS1WAY = OFF // PPSLOCK bit One-Way Set Enable bit (PPSLOCKED bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle)
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON // Low Voltage Programming Enable bit (Low voltage programming enabled. MCLR/VPP pin function is MCLR. MCLRE configuration bit is ignored)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Extended Instruction Set and Indexed Addressing Mode disabled)
// CONFIG5
#pragma config WDTCPS = WDTCPS_31// WDT Period selection bits (Divider ratio 1:65536; software control of WDTPS)
#pragma config WDTE = OFF // WDT operating mode (WDT Disabled; SWDTEN is ignored)
// CONFIG6
#pragma config WDTCWS = WDTCWS_7// WDT Window Select bits (window always open (100%); software control; keyed access not required)
#pragma config WDTCCS = SC // WDT input clock selector (Software Control)
// CONFIG7
#pragma config BBSIZE = BBSIZE_512// Boot Block Size selection bits (Boot Block size is 512 words)
#pragma config BBEN = OFF // Boot Block enable bit (Boot block disabled)
#pragma config SAFEN = OFF // Storage Area Flash enable bit (SAF disabled)
#pragma config DEBUG = OFF // Background Debugger (Background Debugger disabled)
// CONFIG8
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block not Write protected)
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers not Write protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not Write protected)
#pragma config WRTSAF = OFF // SAF Write protection bit (SAF not Write Protected)
#pragma config WRTAPP = OFF // Application Block write protection bit (Application Block not write protected)
// CONFIG10
#pragma config CP = OFF // PFM and Data EEPROM Code Protection bit (PFM and Data EEPROM code protection disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "Q_peripheral27Q43.h"
#include "Q_interrupt27Q43.h"
#include "Q_initialize.h"
#include "Q_I2C1v1.h"
#include "I2C_LCD.h"
#include "MCP23017.h"
void portInit(void);
void oscillatorInit(void);
void vicInit(void);
void main(void)
{
uint16_t val;
//CPUハード初期化-----------------------
portInit();
oscillatorInit();
vicInit();
__delay_ms(100);
//周辺機能初期化--------------------------------
timer0Init();//LED表示
usartInit();
//グローバル割り込み許可------------------------------------------
INTCON0bits.IPEN=1;//プライオリティ無し
INTCON0bits.GIE=1;//Enable all masked interrupts
val=0;
while(1)
{
//Timer0割込み処理-------------------------------------
if(tm0.fg==true)
{
tm0.fg=false;
PORTCbits.RC0=~PORTCbits.RC0;
printf("val=%d\n",val);
val++;
T0CON0bits.EN=1;
PIE3bits.TMR0IE=1;
}
if(rxUsart.completed==true)
{
printf("%s\n",rxUsart.buf);
rxUsart.length=0;
rxUsart.completed=false;
PIE4bits.U1RXIE=1;
}
}
return;
}
void oscillatorInit(void)
{
//オシレータ設定----------------
OSCCON3bits.CSWHOLD=1;//Hold
OSCCON1bits.NDIV=1;//64Mhz/2=32Mhz;
while(!OSCCON3bits.NOSCR);
while(!PIR0bits.CSWIF);//ready state
PIR0bits.CSWIF=0;
OSCCON3bits.CSWHOLD=0;
while(!OSCCON3bits.ORDY);
}
void portInit(void)
{
//ポート設定----------------------
PORTA=0x00;
LATA=0x00;
ANSELA=0x00;
TRISA=0x80;
PORTB=0x00;
LATB=0x00;
ANSELB=0x00;
TRISB=0x00;
PORTC=0x00;
LATC=0x00;
ANSELC=0x00;
TRISC=0x00;
//PPS---------------------
PPSLOCK = 0x55;
PPSLOCK = 0xAA;
PPSLOCKbits.PPSLOCKED = 0;
//I2C1-------------------------
//RC4 for SDA
RC4PPS=0x38;
I2C1SDAPPS=0x14;
//RC3 for SCL
RC3PPS = 0x37;
I2C1SCLPPS=0x13;
PPSLOCK = 0x55;
PPSLOCK = 0xAA;
PPSLOCKbits.PPSLOCKED = 1;
ODCONCbits.ODCC3=1;
ODCONCbits.ODCC4=1;
RC3I2Cbits.TH=1;
RC4I2Cbits.TH=1;
}
void vicInit(void)
{
//割り込みテーブルaddress設定----------------------------------
INTCON0bits.GIE=0;//Enable all masked interrupts
IVTLOCK=0x55;
IVTLOCK=0xAA;
IVTLOCKbits.IVTLOCKED=0;
IVTBASE = 0x000008;
IVTLOCK=0x55;
IVTLOCK=0xAA;
IVTLOCKbits.IVTLOCKED=1;
}