秋月電子の超小型切手サイズPIC18F14K50マイコンボードAE-PIC18F14K50を使って、USB HID デバイスを作ります。
AE-PIC18F14K50
回路の追加
動作確認用に、可変抵抗器、スイッチ、LED、電流制限抵抗を付けます。
確認用なので適当な部品で問題ありません。
回路図
MPLAB X プロジェクトの作成
MPLAB X のインストール、使い方については MPLAB X IDE で PIC18F14K50 にサンプルプロジェクトを書き込む を参照して下さい。
MPLAB X IDE を起動し「File」→「New Project」をクリックします。
「Standalone Project」を選択し「Next >」をクリックします。
「Advanced 8-bit MCUs (PIC 18)」を選択→「PIC18F14K50」を選択→「Show All」をチェックし「PICkit3」を選択し「Next >」をクリックします。
「None」のまま「Next >」をクリックします。
「XC8」を選択し「Next >」をクリックします。
Project Name、Project Locationを入力→「Set as main project」をチェック→「UTF-8」を選択し「Finsh」をクリックします。
新しいプロジェクトができました。
「Projects」ウインドウのプロジェクト名を右クリックして「Properties」をクリックします。
「Show All」をチェックし「PICkit3」を選択し「OK」をクリックします。
「OK」をクリックできない場合はMPLAB X を再起動して下さい。
もう一度「Projects」ウインドウのプロジェクト名を右クリックし「Properties」を表示して「Categories」から「PICkit 3」を選択し、「Option Categories」を「Power」にして、「Power target circuit from PICkit3」のチェックボックスをチェックし「OK」をクリックします。「Voltage Level」は3.25のままで問題ありません。
もう一度「Projects」ウインドウのプロジェクト名を右クリックし「Properties」を表示して「Categories」から「XC8 Compiler」を選択し、「Include directories」の横の「…」をクリックします。
「Browse」をクリックします。
「ファイル名」に「.」(ドット)を入力し「開く」をクリックします。
「OK」をクリックします。
「OK」をクリックします。
これで、プロジェクト名フォルダ内のファイルをインクルードできるようになります。
「Projects」ウインドウの「Source files」を右クリック→「New」→「main.c」をクリックします。
「File Name」を「main」に修正して「Finish」をクリックします。
「main.c」ができました。中身は空っぽです。
一度ビルドしてみましょう。「Build Main Project」をクリックします。
「Output」ウインドウに「BUILD SUCCESSFUL」が出ればOKです。
Microchip Libraries for Applications(MLA)から必要なファイルをコピーします。
Microchip Libraries for Applications(MLA)のインストールについては MPLAB X IDE で PIC18F14K50 にサンプルプロジェクトを書き込む を参照してください。
以下12個のファイルを「プロジェクト名.x」フォルダにコピーしてください。
「プロジェクト名.x」フォルダは、先ほど「main.c」を作ったフォルダです。
C:\microchip\mla\v2018_11_26\apps\usb\device\hid_custom\firmware\demo_src フォルダから
「usb_config.h」
「usb_descriptors.c」
C:\microchip\mla\v2018_11_26\framework\usb\inc フォルダから
「usb.h」
「usb_ch9.h」
「usb_common.h」
「usb_device.h」
「usb_device_hid.h」
「usb_hal.h」
「usb_hal_pic18.h」
C:\microchip\mla\v2018_11_26\framework\usb\src フォルダから
「usb_device.c」
「usb_device_hid.c」
「usb_device_local.h」
コピーしたファイルをプロジェクトに追加します。
「Projects」ウインドウの「Header Files」を右クリックして「Add Exist Item」をクリックします。
9個の「.h」ファイルを選択し「Select」をクリックします。
同様に、3個の「.c」ファイルを「Source Files」に追加します。
ファイルの準備ができました。
「main.c」を開きソースコードを以下に書き換えます。
#include "usb.h"
#include "usb_device_hid.h"
//#include <string.h>
/** CONFIGURATION Bits **********************************************/
#pragma config CPUDIV = NOCLKDIV
#pragma config USBDIV = OFF
#pragma config FOSC = HS
#pragma config PLLEN = ON
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRTEN = OFF
#pragma config BOREN = OFF
#pragma config BORV = 30
#pragma config WDTEN = OFF
#pragma config WDTPS = 32768
#pragma config MCLRE = OFF
#pragma config HFOFST = OFF
#pragma config STVREN = ON
#pragma config LVP = OFF
#pragma config XINST = OFF
#pragma config BBSIZ = OFF
#pragma config CP0 = OFF
#pragma config CP1 = OFF
#pragma config CPB = OFF
#pragma config WRT0 = OFF
#pragma config WRT1 = OFF
#pragma config WRTB = OFF
#pragma config WRTC = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF
#pragma config EBTRB = OFF
#define SYSTEM_Tasks()
#define INTERRUPT __interrupt()
#define FIXED_ADDRESS_MEMORY
#define HID_CUSTOM_OUT_DATA_BUFFER_ADDRESS __at(0x260)
#define HID_CUSTOM_IN_DATA_BUFFER_ADDRESS __at(0x2A0)
unsigned char ReceivedData[64] HID_CUSTOM_OUT_DATA_BUFFER_ADDRESS;
unsigned char SendData[64] HID_CUSTOM_IN_DATA_BUFFER_ADDRESS;
volatile USB_HANDLE USBOutHandle;
volatile USB_HANDLE USBInHandle;
void INTERRUPT SYS_InterruptHigh(void)
{
#if defined(USB_INTERRUPT)
USBDeviceTasks();
#endif
}
void HIDInitialize()
{
USBInHandle = 0;
USBEnableEndpoint(CUSTOM_DEVICE_HID_EP, USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
USBOutHandle = (volatile USB_HANDLE)HIDRxPacket(CUSTOM_DEVICE_HID_EP,(uint8_t*)&ReceivedData[0],64);
}
bool USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, uint16_t size)
{
switch((int)event)
{
case EVENT_TRANSFER:
break;
case EVENT_SOF:
// APP_LEDUpdateUSBStatus();
break;
case EVENT_SUSPEND:
// APP_LEDUpdateUSBStatus();
// SYSTEM_Initialize(SYSTEM_STATE_USB_SUSPEND);
break;
case EVENT_RESUME:
// APP_LEDUpdateUSBStatus();
// SYSTEM_Initialize(SYSTEM_STATE_USB_RESUME);
break;
case EVENT_CONFIGURED:
HIDInitialize();
break;
case EVENT_SET_DESCRIPTOR:
break;
case EVENT_EP0_REQUEST:
USBCheckHIDRequest();
break;
case EVENT_BUS_ERROR:
break;
case EVENT_TRANSFER_TERMINATED:
break;
default:
break;
}
return true;
}
void Read_Write_USB()
{
if( USBGetDeviceState() < CONFIGURED_STATE )
return;
if( USBIsDeviceSuspended() == true )
return;
if(HIDRxHandleBusy(USBOutHandle) == false) //Check if we have received an OUT data packet from the host
{
if(!HIDTxHandleBusy(USBInHandle)) //Check to make sure the endpoint/buffer is free before we modify the contents
{
// for (int i = 0; i < 64; i++)
// SendDataBuffer[i] = ReceivedDataBuffer[i]; //オウム返し
SendData[0] = ReceivedData[0];
USBInHandle = HIDTxPacket(CUSTOM_DEVICE_HID_EP, (uint8_t*)&SendData[0],64); //SendDataBuffeを書き込む
}
USBOutHandle = HIDRxPacket(CUSTOM_DEVICE_HID_EP, (uint8_t*)&ReceivedData[0], 64); //SendDataBuffeに変更有無にかかわらず送信
}
}
void Check_Button()
{
if(!HIDTxHandleBusy(USBInHandle)) //Check to make sure the endpoint/buffer is free before we modify the contents
{
if(PORTBbits.RB7 == 0)
{
SendData[1] = 0x00; //ボタン状態通知
PORTC = 0xFF; //ポートC全部オン
}
else
{
SendData[1] = 0x01; //ボタン状態通知
PORTC = 0x00; //ポートC全部オフ
}
}
}
uint16_t ADC_Read10bit()
{
uint16_t result;
ADCON0bits.CHS = 0b00001010; //CHSが1010 だから 1010 = AN10 RB4
ADCON0bits.GO = 1; // Start AD conversion
while(ADCON0bits.NOT_DONE); // Wait for conversion
result = ADRESH;
result <<=8;
result |= ADRESL;
return result;
}
void Chek_ADC()
{
if(!HIDTxHandleBusy(USBInHandle)) //Check to make sure the endpoint/buffer is free before we modify the contents
{
uint16_t pot = ADC_Read10bit();
SendData[2] = (uint8_t)pot; //LSB
SendData[3] = pot >> 8; //MSB
}
}
void SYSTEM_Initialize()
{
//ADC
ADCON0=0x29; //00 1010 01 CHSが1010:AN10(RB4) A/D 変換サイクル進行中でない ADC を有効にする
ADCON0bits.CHS = 0b00001010; //CHSが1010 だから 1010 = AN10 RB4
ADCON1=0x00; //正電圧リファレンス: VDD 負電圧リファレンス:VSS
ADCON2=0x3E; //0 0 111 110 A/D 変換結果フォーマット:左詰め アクイジション時間:20 TAD A/D 変換クロック:FOSC/64
ADCON2bits.ADFM = 1; // A/D 変換結果フォーマット:= 右詰め
TRISBbits.TRISB4 = 1; //PIN_INPUT 1
ANSELHbits.ANS10 = 1; //RB4 のデジタル入力バッファを無効に設定(過電流防止の為必要)
//Button
TRISBbits.TRISB7 = 1; //1で入力 0で出力 RB7は入力
WPUBbits.WPUB7 = 1; //RB7をプルアップ
INTCON2bits.RABPU = 0; //プルアップ有効
//LED
TRISC = 0x00; //1で入力 0で出力 ポートCは全部出力
}
void main(void)
{
SYSTEM_Initialize(); //AD設定、ポート設定
USBDeviceInit(); //usb_device.c より
USBDeviceAttach(); //usb_device.c より
for (int i = 0; i < 64; i++)
SendData[i] = 0;
for (int i = 0; i < 64; i++)
ReceivedData[i] = 0;
while(1)
{
SYSTEM_Tasks();
Read_Write_USB();
Check_Button();
Chek_ADC();
}//end while
}
「Build Main Project」をクリックして正しくビルドできることを確認します。
書き込みと動作確認
書き込みについては MPLAB X IDE で PIC18F14K50 にサンプルプロジェクトを書き込む を参照してください。
動作確認用のPCアプリケーションは C#でUSB HID通信ホストアプリケーションを作る で作成したアプリケーションを使用してください。
通信モニタが走り、スイッチの状態が切り替わり、AD値が変化すれば正常です。