ここは、PIC18F2550/4550の覚書ページ。環境は以下を想定している。PIC18FはそこそこのCPUパワーに多数のペリフェラルが付いており使いやすい。また、秋月等で販売されており、低価格で入手性も良い。
開発環境:CSS-C(C言語)
ライタ:PIC Programmerv4 Beta
ほとんどは、CSSに付属しているサンプル(Example)で実現できる(サンプルが優秀で使いやすい)。
PIC16F883のRB I/Oポート問題
RB5を入力設定にしたのに常に0にしかならない。
よくよく調べるとRB6,RB7しか反応せず(1を入力すると1を返す)、RB0~RB5は無反応であることが分かった。
原因は、RB0~RB5がアナログ入力になっていたこと。
CCSでは、AN7までしかサポートしていない?ためか、ADCの設定をDISにしてもRB0~RB5はDISにならない。
直接レジスタを叩いてDISにする必要がある。
#BYTE ANSELH = 0x189
ANSELH = 0x00;
PIC18F2550/4550
タイマー1kHz
PIC 18F2550を使用した1kHzタイマー
タイマー:
サンプル
SPI
PIC 18F2550を使用したADC128S052とのSPI通信プログラム
SPI通信:
サンプル
PICでSPIの極性(モード)を変更したい場合、CCSコンパイラでは変更する関数が用意されていないため、直接レジスタを叩く必要がある。0x14はレジスタアドレス、4はbit(0オリジン)である。レジスタアドレスはPICのデータシートに書いてある。叩き方としては、
#BIT CKP = 0x14.4
CKP = 0;
と思ったら用意されていたでござる。
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
setup_spi(SPI_MASTER | SPI_MODE_0);
SPIとTIMER1を同時に使用しようとしたら、急にSPI通信のところで処理が停止してしまう現象が起きた。原因を探っていくと、SPIの初期化をした後に汎用ピンの初期化(set_tris_cとか)をしており、これが原因だった模様。処理順を逆にしたら正常に動作した。
A/Dコンバータ
18F2550のA/D取得。ADC以外も色々書いてあるけども。
A/D取得1:
サンプル
A/D取得2:
サンプル
PWM
PWMによる可変電圧@18F2550
発振周波数2.9kHz、出力段にLPF(RC 10k/5uF)を入れる
PWM:
サンプル
USB(仮想COMポート)
仮想COMポートでPCと通信可能なプログラム。
CCS付属のドライバはXPまでなので、そのままだとWindows7では使えない。色々修正してWindows7でも使用できるようにしたものが以下(自己責任で使用してください)。
src:
サンプル
driver:
ドライバ(windows7対応)
Windows10以降ではセキュリティが強化されており、上記のドライバはインストールがうまく出来なくなっている。
一応、CCSのサイトから
ドライバが一覧にあるが、これが使えるかしら。。。
もしくは、以下を試してみる。
driver:
ドライバ(windows10対応)
USB(HID)
なぜこれで受信できるかよく分かっていない。PIC->PCの送信のみ。CDCのようにポート指定をしたくない場合などに使える。ドライバもOSが持っているので、気にしなくてよい。PCソフトはプロジェクトごとだと重いので、mainのみ。
src:
サンプル
driver:なし(HIDなので自動でインストールされるため)
PCソフト:
サンプル
PIC 18F2550@CDC
PIC 18F2550のUSB接続のF/W(ファームウェア) CDC形式
#define __USB_PIC_PERIF__ 1
#if !defined(__PCH__)
#error USB CDC Library requires PIC18
#endif
#if __USB_PIC_PERIF__
#include <18F2550.h>
//configure a 20MHz crystal to operate at 48MHz
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
//#fuses USBDIV, PLL1, CPUDIV1, PROTECT, NOCPD, noBROWNOUT,HSPLL,NOWDT,nolvp, VREGEN
#use delay(clock=48000000)
#else //use the National USBN960x peripheral
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#endif //endif check to see which peripheral to use
#if __USB_PIC_PERIF__ && defined(__PCH__)
#define USB_CON_SENSE_PIN PIN_B2
#endif
// Includes all USB code and interrupts, as well as the CDC API
#include <usb_cdc.h>
#rom int 0xf00000={1,2,3,4}
void main() {
BYTE i, j, address, value;
usb_cdc_init();
usb_init();
while(!usb_cdc_connected()) {}
do {
usb_task();
if (usb_enumerated()) {
printf(usb_cdc_putc, "\r\n\nEEPROM:\r\n"); // Display contents of the first 64
for(i=0; i<=3; ++i) { // bytes of the data EEPROM in hex
for(j=0; j<=15; ++j) {
printf(usb_cdc_putc, "%2x ", read_eeprom( i*16+j ) );
}
printf(usb_cdc_putc, "\n\r");
}
printf(usb_cdc_putc, "\r\nLocation to change: ");
address = gethex_usb();
printf(usb_cdc_putc, "\r\nNew value: ");
value = gethex_usb();
write_eeprom( address, value );
}
} while (TRUE);
}
PIC動かない事例
- MCLRに電圧がかかっていない
- WDTがONになっている
- PWRTE(電源投入直後に72ms間のリセット)が無効になっている
- 電源電圧が低い
- 低電圧プログラミング(LVP)が有効になっている。
- 発振子の設定が合っていない
PIC書き込めない事例
- PGM端子がプルダウンされていない
- 発振子がプルダウンされていない
- MCLR端子に高電圧がかかっていない
- おかしなGNDが接続されている
- PGC/PGDに何か接続されている
PICトラブル事例
- SPIが使用する端子をI/O入力に設定するとspi_writeした時点でフリーズする。
- 16F883はCCSがADCをAN7?までしかサポートしていない?
CCSでのビットシフト
unsigned char a = 0xab;
unsigned char b = 0xcd;
long c;
c = a << 8 | b;
とすると、bは0x00cdとなってしまう。
これは、a<<8とするとaは1byteであることから0x00となってしまう。
回避するには、
c = a;
c = a << 8 | b;
とする。一度2byteの器に移し替え、ビットシフトを行う必要がある。
CCSでは、short型が2byteない?
ucharを結合する場合は、longを使用した方がよい
PIC18FのUSB機能をOFFに、USB端子をI/Oピンとして使用する
18F系のPICではノミナルで、USB機能がENAとなっている。しかし、場合によってはD+/-端子をI/Oピンとして使用したい時があり、その場合はUSB機能をDISにする必要がある。下記のようにレジスタを設定する。
#include "./sample.h"
#byte UCON=0xF6D
#bit USBEN=UCON.3
#byte UCFG=0xF6F
#bit UTRDIS=UCFG.3 // USB Tranceiver Disable flg
#byte RCSTA=0xFAB
#bit SPEN=RCSTA.7
void main()
{
USBEN = 0;
SPEN = 0;
UTRDIS=1;
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(False);
// TODO: USER CODE!!
}
最終更新:2018年04月21日 21:17