「PIC」の編集履歴(バックアップ)一覧はこちら
「PIC」(2018/04/21 (土) 21:17:14) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
ここは、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タイマー
タイマー:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=foucault.c]]
*SPI
PIC 18F2550を使用したADC128S052とのSPI通信プログラム
SPI通信:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=pic_spi.zip]]
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:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=adc.c]]
A/D取得2:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=CH.c]]
*PWM
PWMによる可変電圧@18F2550
発振周波数2.9kHz、出力段にLPF(RC 10k/5uF)を入れる
PWM:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=pwm.c]]
*USB(仮想COMポート)
仮想COMポートでPCと通信可能なプログラム。CCS付属のドライバはXPまでなので、そのままだとWindows7では使えない。色々修正してWindows7でも使用できるようにしたものが以下(自己責任で使用してください)。
src:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=ex_usb_serial.c]]
driver:[[ドライバ(windows7対応)>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=driver.zip]]
Windows10以降ではセキュリティが強化されており、上記のドライバはインストールがうまく出来なくなっている。
一応、CCSのサイトから[[ドライバ>http://www.ccsinfo.com/downloads.php]]が一覧にあるが、これが使えるかしら。。。
もしくは、以下を試してみる。
driver:[[ドライバ(windows10対応)>https://img.atwikiimg.com/www13.atwiki.jp/usonx/attach/13/189/NT%2C2000%2CXP%2CVISTA%2C7%2C8%2C10.zip]]
*USB(HID)
なぜこれで受信できるかよく分かっていない。PIC->PCの送信のみ。CDCのようにポート指定をしたくない場合などに使える。ドライバもOSが持っているので、気にしなくてよい。PCソフトはプロジェクトごとだと重いので、mainのみ。
src:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=ex_usb_hid.c]]
driver:なし(HIDなので自動でインストールされるため)
PCソフト:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=MFC_USBHIDDlg.cpp]]
----
*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!!
}
----
ここは、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タイマー
タイマー:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=foucault.c]]
*SPI
PIC 18F2550を使用したADC128S052とのSPI通信プログラム
SPI通信:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=pic_spi.zip]]
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:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=adc.c]]
A/D取得2:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=CH.c]]
*PWM
PWMによる可変電圧@18F2550
発振周波数2.9kHz、出力段にLPF(RC 10k/5uF)を入れる
PWM:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=pwm.c]]
*USB(仮想COMポート)
仮想COMポートでPCと通信可能なプログラム。
CCS付属のドライバはXPまでなので、そのままだとWindows7では使えない。色々修正してWindows7でも使用できるようにしたものが以下(自己責任で使用してください)。
src:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=ex_usb_serial.c]]
driver:[[ドライバ(windows7対応)>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=driver.zip]]
Windows10以降ではセキュリティが強化されており、上記のドライバはインストールがうまく出来なくなっている。
一応、CCSのサイトから[[ドライバ>http://www.ccsinfo.com/downloads.php]]が一覧にあるが、これが使えるかしら。。。
もしくは、以下を試してみる。
driver:[[ドライバ(windows10対応)>https://img.atwikiimg.com/www13.atwiki.jp/usonx/attach/13/189/NT%2C2000%2CXP%2CVISTA%2C7%2C8%2C10.zip]]
*USB(HID)
なぜこれで受信できるかよく分かっていない。PIC->PCの送信のみ。CDCのようにポート指定をしたくない場合などに使える。ドライバもOSが持っているので、気にしなくてよい。PCソフトはプロジェクトごとだと重いので、mainのみ。
src:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=ex_usb_hid.c]]
driver:なし(HIDなので自動でインストールされるため)
PCソフト:[[サンプル>http://www13.atwiki.jp/usonx?cmd=upload&act=open&pageid=13&file=MFC_USBHIDDlg.cpp]]
----
*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!!
}
----