シリアル通信で制御できるMP3プレイヤー
DFPlayerMini 秋月電子で購入。 SDカードの読み出し、DAコンバータ出力、アンプ出力をやってくれます。 コマンドを一つ出せば、すぐに音声ファイルを再生してくれます。 スピーカを直接接続できます。内蔵のオペアンプも、いい音を出します。
DFPlayerMini 再生ファイルのフォーマットについて
mp3、wavファイルは、ステレオでフォーマットされている必要があります。
モノラル形式で保存された場合、再生はされますが、再生終了レスポンス(0x3D)が正常に動作しません。
再生終了レスポンス(0x3D)は、通常2つ連続で返信されてきます。つまり、LeftとRightのデータが終端に到達すると、2つのレスポンスが送信されるようになっていると、想定されます。
なので、モノラルのばあい、LEFT、RIGHT双方のデータが格納されている必要があります。片方だけのファイルの場合、DFPlayerMiniが正常に動作しないと想定されます。

DFPlayerMini シリアル通信 通信フォーマット
$7 VER Len CMD Feedback para1 para2 checkSum1 checkSum2 END
7E FF 06 xx 00 xx xx xx xx EF(checksumあり10byte)
7E FF 06 xx 00 xx xx EF(checksumなし8byte)
パケットは、チェックサムありの10バイト、なしの8バイト。どちらでも、通信できます。
| バイト番号 | 意味 | |||
|---|---|---|---|---|
| 0 | $S | ヘッダー | 0x7E | 開始文字 |
| 1 | VER | バージョン | 0xFF | バージョン情報 |
| 2 | Len | 送信長 | 0x06 | このバイト以降の送信数 |
| 3 | CMD | コマンド | ||
| 4 | Feedback | レスポンス | 0x0- | 0x00:なし 0x01:あり |
| 5 | para1 | パラメータ1 | 0x-- | 上位バイト |
| 6 | para2 | パラメータ2 | 0x-- | 下位バイト |
| 7 | checkSum | チェックサム1 | 0x-- | 上位バイト |
| 8 | checkSum | チェックサム2 | 0x-- | 下位バイト |
| 9 | END | フッター | 0xEF | 終端文字 |
チェックサムの計算方法

revisionからpara2までの6バイトを対象にします。
6バイトを単純に16ビット変数で、加算します。
それから、上記のように、XORをとりビットを反転させます。
さらに1を加算すると、2の補数になります。
6バイトの合計とチェックサムを足すと、ゼロになります。
DFPlayerMini 設定コマンド群 (返信なし)
最もよく使うコマンド群です。
コマンド送信フォーマット
7E FF 06 CMD 00 para1 para2 xx xx EF (10byte)
7E FF 06 CMD 00 para1 para2 EF (8byte)
※チェックサムはなくても、OK。
| CMD | 機能 | パラメータ(2byte) | 内容 |
|---|---|---|---|
| 0x01 | Next | - | 次 |
| 0x02 | Previous | - | 前 |
| 0x03 | Specify Track | 0-2999 | 再生:トラック番号 |
| 0x04 | IncreaseVolume | 音量+ | |
| 0x05 | DecreaseVolume | 音量ー | |
| 0x06 | SpecifyVoluem | 0-30 | 音量設定 |
| 0x07 | SpecifyEQ | 0-5 | Normal/Pop/Jazz/Classic/Base |
| 0x08 | PlayMode | 0-3 | リピート、シングル再生設定 |
| 0x09 | PlaySource | 0-4 | 再生デバイス設定 |
| 0x0A | StanbyMode | スタンバイ設定 | |
| 0x0B | NormalWorking | ? | |
| 0x0C | ResetModue | リセット | |
| 0x0D | PlayBack | 再生 | |
| 0x0E | Pause | 一時停止 | |
| 0x0F | Specify folder | 01-99,001-255 | 再生:フォルダ、トラック指定 |
| 0x10 | VolumeAdjust | ? | |
| 0x11 | RepeatPlay | ? | |
| 0x16 | Stop | 停止 |
DFPlayerMini Queryコマンド(質問コマンド、返信あり)
DFPlayer内の設定やステータスを読むためのクエリーコマンド群です。
コマンド送信(0x4E) フォルダ内のトラック数をしらべる
7E FF 06 4E 00 00 para1 xx xx EF (10byte)
7E FF 06 4E 00 00 para1 EF (8byte)
para1にフォルダ番号を指定
レスポンス
7E FF 06 4E 00 para1 para2 xx xx EF (10byte)
| CMD | パラメータ1 | パラメータ1 | 内容 |
|---|---|---|---|
| 0x4E | 上位バイト | 下位バイト | トラック数 |
コマンド送信(0x4F) ルートのフォルダ数を調べる
7E FF 06 4F 00 00 00 xx xx EF (10byte)
7E FF 06 4F 00 00 00 EF (8byte)
レスポンス
7E FF 06 4F 00 para1 para2 xx xx EF (10byte)
| CMD | パラメータ1 | パラメータ1 | 内容 |
|---|---|---|---|
| 0x4F | 上位バイト | 下位バイト | SDカードのフォルダ数 |
DFPlayerMini ドライバーコード
DFPlayerMiniの初期化処理は、まったくありません。ただし、音量がデフォルトで、MAX30になっているので、音量を起動時に下げておく必要があります。あとは、再生コマンドを送信すれば、音声を再生できます。
チェックサムは、パケットのrevisionからpara2までの6バイトを単純に加算した後、その値を2の補数に変換します。それがチェックサムになります。
PICマイコンの電源は、3.3V。
DFPlayerMiniの電源も、3.3V。
PICマイコンのRB3に、DFPlayerのBusy端子を接続しています。
Busy端子はアクティブロー出力で、Lowのときは再生中。Highのときは、停止中です。
このBusy信号をポーリングして、つぎの曲の再生コマンドを送信します。
PIC16F1827ピン配
| pin | name | 機能 | 説明 | pin | name | 機能 | 説明 |
|---|---|---|---|---|---|---|---|
| 17 | RA0 | IO入力 | スイッチ | 6 | RB0 | ||
| 18 | RA1 | 7 | RB1 | MSSP1 | I2C1 SDA1 | ||
| 1 | RA2 | 8 | RB2 | USART | RX | ||
| 2 | RA3 | 9 | RB3 | Busy信号 | DFPlayer | ||
| 3 | RA4 | 10 | RB4 | MSSP1 | I2C1 SCK1 | ||
| 7 | RA5 | /MCLR | 11 | RB5 | USART | TX | |
| 15 | RA6 | 12 | RB6 | ICSCLK | 書き込み線 | ||
| 16 | RA7 | 13 | RB7 | ICSDAT | 書き込み線 |
/*
* File: DFPlayer.h
* Author: h
*
* Created on 2025/11/20, 9:21
*/
#ifndef DFPLAYER_H
#define DFPLAYER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <xc.h>
//コマンド
#define CMD_Next 0x01
#define CMD_Previous 0x02
#define CMD_SpecifyTrack 0x03 //0-2999
#define CMD_IncVolume 0x04
#define CMD_DecVolume 0x05
#define CMD_SpecifyVol 0x06 //0-30
#define CMD_SpecifyEQ 0x07 //Normal/Pop/Rock/Jazz/Classic/Base
#define CMD_SpecifyPlayMode 0x08 //Repeat/folder repeat/single repeat/random
#define CMD_SpecifyPlaySouce 0x09 //0:U 1:TF
#define CMD_EnterStanby 0x0A
#define CMD_NormalWorking 0x0B
#define CMD_Reset 0x0C
#define CMD_PlayBack 0x0D
#define CMD_Pause 0x0E
#define CMD_SpecifyFolder 0x0F //1-10(need to set by user)
#define CMD_VolumeAdjust 0x10
#define CMD_RepetPlay 0x11 1:start repeat 0:stop play
#define CMD_Stop 0x16
#define CMD_Q_FileNumber 0x4E
#define CMD_Q_FolderNumber 0x4F
//チェックサム用
typedef struct
{
uint8_t high;//7バイト目
uint8_t low;//8バイト目
}_DFPlayer_checkSum;
/*
* 送信データセット用構造体
*コマンドフォーマット
*[0][1][2][3] [4] [5] [6] [7] [8] [9]
* 7E FF 06 CMD 00 parm1 para2 chs1 chs2 EF
*/
typedef union
{
struct{
uint8_t header; //0バイト目
uint8_t version; //1バイト目
uint8_t length; //2バイト目
uint8_t cmd; //3バイト目
uint8_t feedBack; //4バイト目
uint8_t para1; //5バイト目
uint8_t para2; //6バイト目
_DFPlayer_checkSum checkSum; //7,8バイト目
uint8_t fotter; //9バイト目
};
uint8_t txData[10];//送信バッファ
}_DFPlayer_txData;
typedef struct
{
uint8_t maxTrackNumber; //総トラック数(指定フォルダ内)
uint8_t maxFolderNumber; //総フォルダ数
}_DFPlayerData;
extern _DFPlayerData DFPlayerData;
extern _DFPlayer_txData DFPlayer;
//DFPlayer制御関数
extern void DFPlayerInitialize(void);
extern void DFPlayerCalcCheckSum(void);
extern void DFPlayerSendCommand(uint8_t cmd, uint8_t para_high, uint8_t para_low);
//コマンド
extern void DFPlayerStop(void); //再生停止(0x16)
extern void DFPlayerQueryMaxTrackNumber(uint8_t folderNumber);//ファイル数(0x4E)
extern void DFPlayerQueryMaxFolderNumber(void); //フォルダ数(0x4F)
#ifdef __cplusplus
}
#endif
#endif /* DFPLAYER_H */
#include "DFPlayer.h"
#include "Peripheral.h"
#include "LCDdriver.h"
_DFPlayerData DFPlayerData;
_DFPlayer_txData DFPlayer;
/**
* 関数名:DFPlayerInitialize
* 初期化関数
* 使用上特別に設定することはなし。
* 音量は、MAX30がデフォルトなので、下げる。
*/
void DFPlayerInitialize(void)
{
//コマンドパケットのセット(定型部分を先にセット)
DFPlayer.header = 0x7E;
DFPlayer.version = 0xFF;
DFPlayer.feedBack = 0x00;
DFPlayer.length = 6;
DFPlayer.fotter = 0xEF;
//起動待機 ------------------------------
__delay_ms(1000);
//音量設定コマンド (0x06)-----------------
DFPlayerSendCommand(CMD_SpecifyVol,0x00,0x19);
__delay_ms(100);
}
/**
* 関数名:DFPlayerCalcCheckSum
* チェックサムを求める
* Versionからpara2まで、
* 単純加算後、2の補数として計算する。
*/
void DFPlayerCalcCheckSum(void)
{
uint8_t i;
uint16_t buf;
buf=0;
for(i=1; i<=6; i++)
{
buf+=DFPlayer.txData[i];
}
//2の補数にする。
buf =buf^0xFFFF;
buf+=1;
DFPlayer.checkSum.high = (uint8_t)(buf>>8);
DFPlayer.checkSum.low = (uint8_t)(buf&0x00FF);
}
/**
* 関数名:DFPlayerSendCommand
* コマンド送信
* 定型部分は、初期化関数でセットしてある。
* @param cmd コマンド
* @param para_high パラメータ上位バイト
* @param para_low パラメータ下位バイト
*/
void DFPlayerSendCommand(uint8_t cmd, uint8_t para_high, uint8_t para_low)
{
uint8_t i;
DFPlayer.cmd=cmd; //コマンドのセット
DFPlayer.para1 = para_high;//パラメータ1のセット
DFPlayer.para2 = para_low; //パラメータ2のセット
DFPlayerCalcCheckSum();//チェックサムの計算とデータセット
for(i=0; i<=9; i++)
{
putch(DFPlayer.txData[i]);//パケット10バイトの送信
}
}
//コマンド群-----------------------------------------------------
/**
* 関数名:DFPlayerStop
* 再生停止コマンド
*/
void DFPlayerStop()
{
DFPlayerSendCommand(CMD_Stop,0x00,0x00);
}
/**
* 関数名:DFPlayerQueryMaxTrackNumber
* 指定したフォルダ内のファイル数を読みだす。
* @param folderNumber 検索するフォルダ番号01-99
*/
void DFPlayerQueryMaxTrackNumber(uint8_t folderNumber)
{
uint8_t length=0;//sprint用
uint8_t txt[3];//LCD用
DFPlayerData.maxTrackNumber=0x00;
DFPlayerSendCommand(CMD_Q_FileNumber,0x00,folderNumber);
//レスポンス待機開始。
RCSTAbits.CREN=1;
PIE1bits.RCIE=1;
while(!usart.rxCompleted);
if(usart.rxBuf[3]==CMD_Q_FileNumber)
{//受信成功
length = sprintf(txt,"%02d",usart.rxBuf[6]);
LCD_Printf(LcdDeviceAdd,txt,length,0x8C);
DFPlayerData.maxTrackNumber=usart.rxBuf[6];
}
RCSTAbits.CREN=1;
PIE1bits.RCIE=1;
usart.rxCompleted=false;
usart.length=0;
}
/**
* 関数名:DFPlayerQueryMaxFolderNumber
* ルートにあるフォルダの数を取得
* 隠れファイルが一つあるので、マイナス1する。
*/
void DFPlayerQueryMaxFolderNumber(void)
{
uint8_t length=0;
uint8_t txt[3];
DFPlayerData.maxFolderNumber=0x00;
DFPlayerSendCommand(CMD_Q_FolderNumber,0x00,0x00);
//レスポンス待機開始。
RCSTAbits.CREN=1;
PIE1bits.RCIE=1;
while(!usart.rxCompleted);
if(usart.rxBuf[3]==CMD_Q_FolderNumber)
{//受信成功
length = sprintf(txt,"%02d",usart.rxBuf[6]);
LCD_Printf(LcdDeviceAdd,txt,length,0x8C);
DFPlayerData.maxFolderNumber=usart.rxBuf[6]-1;//隠れファイル-1
}
RCSTAbits.CREN=1;
PIE1bits.RCIE=1;
usart.rxCompleted=false;
usart.length=0;
}
// PIC16F1827 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1
#pragma config FOSC = HS // Oscillator Selection (HS Oscillator, High-speed crystal/resonator connected between OSC1 and OSC2 pins)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config DEBUG = ON // In-Circuit Debugger Mode (In-Circuit Debugger enabled, ICSPCLK and ICSPDAT are dedicated to the debugger)
#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <stdlib.h>
#include <stdio.h>
#include "Interrupt.h"
#include "Peripheral.h"
#include "I2C_MSSP1.h"
#include "LCDdriver.h"
#include "DFPlayer.h"
void Oscillator_Init(void);
void Port_Init(void);
uint8_t txt[20];//LCD用
void main(void)
{
uint8_t length;//sprint用
uint8_t trackNumber,folderNumber;
//MCU初期化
Oscillator_Init();
Port_Init();
//Peripheral initializing
USART_INIT();//USART初期化
I2C1_Reg_Init();//MSSP1初期化
LCD_Init(LcdDeviceAdd);//LCD初期化
//LCD初期化後は、I2Cの速度を上げる
//SSP1ADD=0x13; //Fosc=32MHz Fclock=400kHz
SSP1ADD=0x09;//Fosc=32MHz Fclock=800kHz
//DFPlayer初期化
DFPlayerInitialize();
DFPlayerData.maxTrackNumber=3; //総トラック数(特定フォルダ内)
DFPlayerData.maxFolderNumber=3;//総フォルダ数
folderNumber=1;//フォルダ番号カウンタ
trackNumber=1;//トラック番号カウンタ
//LCD表示
LCD_Printf(LcdDeviceAdd,"Folder:",7,0x80);
LCD_Printf(LcdDeviceAdd,"PlayNumber:",11,0xC0);
//割り込み許可
Interrupt_START();
//例:総フォルダ数、総トラック数を取得する関数
//#define EN1
#ifdef EN1
//SDカードのルートにある総フォルダ数の取得
DFPlayerQueryMaxFolderNumber();
while(PORTAbits.RA0==1);
__delay_ms(300);
//フォルダ01にあるトラック数の取得
DFPlayerQueryMaxTrackNumber(1);
while(PORTAbits.RA0==1);
__delay_ms(300);
#endif
while(1)
{
//USART 受信割り込み処理
if(usart.rxCompleted)
{
LATAbits.LATA2=~LATAbits.LATA2;
//レスポンスの内容を表示。
usart.rxCompleted=false;
usart.length=0;
}
//再生コマンド処理 RB3にDFPlayerのBusy端子がつながっています。
if(PORTBbits.RB3==1)//再生停止中。Busy信号:1 再生中:0
{
//再生コマンド送信
DFPlayerSendCommand(CMD_SpecifyFolder, folderNumber, trackNumber);
//LCDに再生場所を表示
length = sprintf(txt,"%02d",folderNumber);
LCD_Printf(LcdDeviceAdd,txt,length,0x87);
length = sprintf(txt,"%03d",trackNumber);
LCD_Printf(LcdDeviceAdd,txt,length,0xCB);
//フォルダ番号とファイル番号のカウント
trackNumber++;
if(trackNumber>DFPlayerData.maxTrackNumber)
{
trackNumber=1;
folderNumber++;
if(folderNumber>DFPlayerData.maxFolderNumber)
{
folderNumber=1;
}
}
while(PORTBbits.RB3==1);
RCSTAbits.CREN=1;
PIE1bits.RCIE=1;
}
}
return;
}
//外付けセラロック8MHzを使用Fosc=8*4=32MHz
void Oscillator_Init(void)
{
OSCCONbits.SPLLEN=1;
//OSCCONbits.IRCF=0b1110;//8Mhz
OSCCONbits.SCS=0b00;// Clock determined by FOSC<2:0>
}
void Port_Init(void)
{
TRISA=0x01; //ボタン入力
ANSELA=0x00;
TRISB=0x08; //RB3:DFPlayer Busy信号入力
ANSELB=0x00;
PORTA=0x00;
PORTB=0x00;
//Altanative Pin Selective
APFCON0bits.RXDTSEL=1; //RX:RB2
APFCON1bits.TXCKSEL=1; //TX:RB5
TRISBbits.TRISB2=1;
//I2Cinitialize
TRISBbits.TRISB1=1; //RB1
TRISBbits.TRISB4=1; //RB4
}
#ifndef INTERRUPT_H
#define INTERRUPT_H
#ifdef __cplusplus
extern "C" {
#endif
extern void __interrupt()isr();
#ifdef __cplusplus
}
#endif
#endif /* INTERRUPT_H */
#include <pic16f1827.h>
#include "Peripheral.h"
#include "Interrupt.h"
#include "I2C_MSSP1_Slave.h"
void __interrupt()isr()
{
uint8_t ch;
uint8_t temp;
//USART受信割り込み処理
if(PIE1bits.RCIE==1 && PIR1bits.RCIF)
{
LATAbits.LATA1=~LATAbits.LATA1;
PIR1bits.RCIF=0;
//USART error check-----------------------
if(RCSTAbits.OERR)
{
RCSTAbits.CREN=0;
RCSTAbits.CREN=1;
}
if(RCSTAbits.FERR)
temp=RCREG;
//受信バッファから取り出し-------------------
ch =(uint8_t)getch();
usart.rxBuf[usart.length++]=ch;
//-----------------------------------
if(usart.length>=rxLength)
{//受信バッファが満杯。
usart.length=0;
usart.rxCompleted=true;
RCSTAbits.CREN=0;
PIE1bits.RCIE=0;
}
//受信完了
if(ch==0xEF && usart.length==0x0A)
{//終端文字の受信
usart.rxCompleted=true;
RCSTAbits.CREN=0;
PIE1bits.RCIE=0;
}
}
}
#ifndef PERIPHERAL_H
#define PERIPHERAL_H
#include <xc.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define _XTAL_FREQ 32000000
#ifdef __cplusplus
extern "C" {
#endif
//**************************************************//
// USART
//**************************************************//
#define BAUDRATE 9600
//#define BAUDRATE 115200
#define SET_SPBRG_DATA2 (((unsigned int)((_XTAL_FREQ/64)/BAUDRATE))-1)
#define SET_SPBRG_DATA (((unsigned int)((_XTAL_FREQ/16)/BAUDRATE))-1)
#define SET_SPBRG_DATA1 (((unsigned int)((_XTAL_FREQ/4)/BAUDRATE))-1)
extern void USART_INIT(void);
//extern void putch(uint8_t byte);
//extern uint8_t getch(void);
#define rxLength 11
typedef struct {
uint8_t length;
uint8_t rxBuf[60];
bool rxCompleted;
}_usart;
extern volatile _usart usart;
#define rxBuffer_length 30
typedef struct{
uint8_t ch;
uint8_t Buffer[rxBuffer_length];
uint8_t index;
uint8_t Completed;
}_rx;
extern _rx rx;
//************************************************//
//Timer0 8bits timer
//************************************************//
#define T0_UP 1
#define T0_STOP 0
typedef struct{
bool up;
uint16_t cnt;
}_tm0;
extern _tm0 tm0;
//************************************************//
//Timer1
//************************************************//
#define T1_UP 1
#define T1_STOP 0
typedef struct{
bool up;
uint16_t cnt;
}_tm;
extern _tm tm1;
//************************************************//
//ADC
//************************************************//
#define ADC_Sampling_Num 10
typedef struct{
uint8_t Ch;
uint16_t val;
bool Completed;
uint16_t data[ADC_Sampling_Num+1];
uint8_t index;
uint16_t RMS;
int32_t cal;
}_ADC;
extern _ADC ADC;
extern void Timer0_INIT(void);
extern void Timer1_INIT(void);
extern void Timer2_INIT(void);
extern void Timer4_INIT(void);
extern void Timer6_INIT(void);
extern void Interrupt_START(void);
extern void ADC_INIT(void);
extern void CCP1_PWM_Init(void);
extern void CCP2_PWM_Init(void);
extern void CCP3_PWM_Init(void);
extern void CCP4_PWM_Init(void);
#ifdef __cplusplus
}
#endif
#endif /* MYLIB_H */
#include "Peripheral.h"
/*-----------------------------------------
*USART
*-----------------------------------------*/
volatile _usart usart;
_rx rx;
void USART_INIT(void)
{
uint8_t buf;
unsigned int brg;
//SPBRG value set
brg = SET_SPBRG_DATA2;
SP1BRGL =(unsigned char) brg;
SP1BRGH =(unsigned char) (brg>>8);
//TX-------------------------------------
TXREG=0x00;
//TXSTA SYNC:1 BRGH:1 TXEN:1 TX9:0
buf =TXSTA & 0x83;
TXSTA = buf | 0x20;
//TXSTA = buf | 0x24;
//RX-------------------------------------
//RCSTA SPEN:1 RX9:0 CREN:1
buf =RCSTA & 0x2F;
RCSTA =buf | 0x90;
//BAUR RATE CONTROL REGISTER
BAUDCON = 0x00;
//BAUDCON = 0x08;
//if interrupt is desired, TXIE set(PIE1)
PIE1bits.TXIE=0;//disable
//if interrupts are desired, RCIE set(PIE1)
PIE1bits.RCIE=1;//enable
usart.length=0;
usart.rxCompleted=false;
}
void putch(char byte)
{
while(!PIR1bits.TXIF)continue;
TXREG=byte;
}
int getch(void)
{
while(!PIR1bits.RCIF){};
return RCREG;
}
/*---------------------------------------------------
Timer0 8bits Timer
---------------------------------------------------*/
_tm0 tm0;
void Timer0_INIT(void)
{
OPTION_REGbits.TMR0CS = 0; //ClockSource:Fosc/4
OPTION_REGbits.PSA = 0; //assingned to the Timer0
OPTION_REGbits.PS = 0b111; //1:256
TMR0=0x63; //Fosc:32Mhz interval time 10ms
INTCONbits.T0IE = 1;
tm0.cnt=0;
}
/*---------------------------------------------------
Timer1
---------------------------------------------------*/
_tm tm1;
void Timer1_INIT(void)
{
TMR1L=0x0B;//16MHz 1ms PSC:1:8
TMR1H=0xFE;
T1CON=0x31;
T1GCON=0x00;
PIE1bits.TMR1IE=1;
tm1.up=T0_STOP;
tm1.cnt=0x0000;
}
/*-------------------------------------------
Timer2
--------------------------------------------*/
void Timer2_INIT(void)
{
T2CONbits.T2OUTPS=0b0000;//post sc 1:1
T2CONbits.T2CKPS=0b00;//PSC 1:1
T2CONbits.TMR2ON=1;
PR2=0x50;//10us matching. Fosc=32Mhz
TMR2=0;
PIR1bits.TMR2IF=0;
PIE1bits.TMR2IE=1;
}
/*---------------------------------------------------
Timer4
---------------------------------------------------*/
void Timer4_INIT(void)
{
T4CONbits.T4OUTPS=0b1111;//1:16 Postscaler
TMR4=0;
T4CONbits.T4CKPS=0b01;//prescle1:4
PR4=0x4B;
PIE3bits.TMR4IE=1;
PIR3bits.TMR4IF=0;
T4CONbits.TMR4ON=1;
}
/*---------------------------------------------------
Timer6
---------------------------------------------------*/
void Timer6_INIT(void)
{
T6CONbits.T6OUTPS=0b0000;//1:16 Postscaler
T6CONbits.T6CKPS=0b11;//prescle1:16
T6CONbits.TMR6ON=1;
PR6=0xFA;
TMR6=0;
PIR3bits.TMR6IF=0;
PIE3bits.TMR6IE=1;
}
//interrupt start
void Interrupt_START(void)
{
INTCONbits.PEIE=1;
INTCONbits.GIE=1;
}
/*---------------------------------------------------
AD converter
-------------------------------------------------------*/
_ADC ADC;
void ADC_INIT(void)
{
uint8_t buf;
//1.Configure PortA
buf=TRISA;
TRISA=buf|0x01;
ANSELA|=0x01;
//2.Configure the ADC module
ADCON1bits.ADFM=1; //Right justified.
ADCON1bits.ADCS=0b101; //FOSC/16 Select ADC conversion clock
ADCON1bits.ADNREF=0; //Vref-:AVss Configure voltage referrence
ADCON1bits.ADPREF=0b00; //Vref+ is connected to Vdd.
ADCON0bits.CHS=0x00; //RA0:Select ADC input channel
//Turn on ADC module
ADCON0bits.ADON=1;
PIR1bits.ADIF=0;
PIE1bits.ADIE=1;
//ADC struct data initialize
ADC.index=0;
ADC.cal=0;
ADC.Completed=false;
}
/*----------------------------------------------*/
//PWM
/*-----------------------------------------------*/
//RB0
void CCP1_PWM_Init(void)
{
CCP1CONbits.CCP1M=0b1100;//PWMmode
CCPTMRSbits.C1TSEL0=0b00;//Timer2 in PWM mode
CCPR1L=0x00;
TRISB0=0;
APFCON0bits.CCP1SEL=1;//RB0
}
//RA7
void CCP2_PWM_Init(void)
{
CCP2CONbits.CCP2M=0b1100;//PWMmode
CCPTMRSbits.C2TSEL0=0b00;//Timer2 in PWM mode
CCPR2L=0x00;
TRISA7=0;
APFCON0bits.CCP2SEL=1;//RA7
}
//RA3
void CCP3_PWM_Init(void)
{
CCP3CONbits.CCP3M=0b1100;//PWMmode
CCPTMRSbits.C3TSEL0=0b00;//Timer2in PWM mode
CCPR3L=0x00;
TRISA3=0;
}
//RA4
void CCP4_PWM_Init(void)
{
CCP4CONbits.CCP4M=0b1100;//PWMmode
CCPTMRSbits.C4TSEL0=0b00;//Timer2in PWM mode
CCPR4L=0x00;
TRISA4=0;
}








