やるべき機能 †
- 書き込み
- Digital IO/Analog I
- タイマー割り込み→TMR0
- PWM
- 外部通信(USERT, I2C, SPI)
データシート疑問点とその解決 †
- RA0 General Purpose IO
- AN0 AD Channel
- レジスタには行があり、Bankとよぶ(00-1F, 90-9Fのように)
- PORTAが双方向ポートで、TRISAがその向き。
- ANSELはinputのみをアナログにする?
- アセンブリ用語
- W アキュムレータ(一般用語)、ワーキングレジスタ(PIC用語)。tmp変数に相当。
- F Function Register: そこに読み書きするとビヘイビアが出たり読めたりする。(TRIS, Rなど)
- L リテラル
- prescaler 分周器
- Communication 通信
- SINGLE IN-LINE CONNECTOR ピンソケット
PIC16F887 †
環境設定 †
- MPLABをインストール(Windows版は不安定との噂)
- XC8 compilerをインストール
デジタル入出力 †
#include <xc.h>
#pragma config BOREN = OFF
#pragma config CPD = OFF
#pragma config FOSC = INTRC_CLKOUT
#pragma config MCLRE = OFF
#pragma config WDTE = OFF
#pragma config CP = OFF
#pragma config LVP = OFF
#pragma config PWRTE = ON
#define _XTAL_FREQ 5000000
// Timer Interrupt Function
int count = 0;
void interrupt InterTimer(void)
{
if (T0IF) {
TMR0 = 10, T0IF = 0; // reset TMR0 and T0IF
count++;
RA1 = (count & 0xFFF > 0x8FF);
}
}
#define T2_DIV_BY_1 0b00000000
#define T2_DIV_BY_4 0b00000001
#define T2_DIV_BY_16 0b00000010
#define CCP_PWM 0b00001100
#define PR2_DATA 0xFF
void setPWM1Duty(unsigned int duty)
{
CCPR1L = duty >> 2;
CCP1CON &= 0b11001111;
CCP1CON |= 0b00110000 & (duty << 4);
}
void setPWM2Duty(unsigned int duty)
{
CCPR2L = duty >> 2; // set lower 8 bit
CCP2CON &= 0b11001111; // clear and
CCP2CON |= 0b00110000 & (duty << 4); // set upper 2 bit
}
void initTimer2(unsigned char pr2, unsigned char t2ckps)
{
PR2 = pr2;
T2CON = t2ckps; // set prescalar
T2CON |= 0x04; // timer 2 on
}
void initPWM1(void)
{
CCP1CON = CCP_PWM; // single PWM
setPWM1Duty(0);
}
void initPWM2(void)
{
CCP2CON = CCP_PWM; // simgle PWM
setPWM2Duty(0);
}
int main(void) {
// GPIO settings
ANSEL = 0b10000000; // addddddd
TRISA = 0b11110000; // iiiioooo
TRISC = 0b00000000; // oooooooo for PWM (= CCP and GPIO out and Timer)
// Analog setting
ADCON0 = 0b00000001; // enagle ADC
ADCON0 &= 0b11000011; // clear reading mode
ADCON0 |= 0b00011100; // reading-AN7 mode
ADCON1 = 0b10000000; // right justified, base vol. is VSS/VDD
/* Timer Interrupt */
// Timer 0 interrupt (prescalar 111=1/256)
OPTION_REG = 0b00000111;
TMR0 = 10; // Init timer 0
T0IF = 0; // Timer 0 Interrupt Flag
T0IE = 1; // Timer 0 Interrupt Enable
GIE = 1; // Global Interrupt Enable (if 0, all is disabled)
// PWM (Use Timer 2 and Comparator 1, 2)
initTimer2(PR2_DATA, T2_DIV_BY_1);
initPWM1();
initPWM2();
setPWM1Duty(0);
setPWM2Duty(0);
while (1) {
// Digital IO (RA5)
RA3 = RA5;
// Delay
RA0 = 1;
__delay_ms(150);
RA0 = 0;
__delay_ms(150);
// PWM
setPWM1Duty(1023);
// Analog Read (the output is PWM2)
GO_DONE = 1;
while(GO_DONE);
setPWM2Duty((ADRESH << 8) | ADRESL);
}
}
delay †
- __delay_us, __delay_msを利用する。
- 引数に変数を入力してはいけない
- 可変にしたい場合は、以下のようにする。
#define _XTAL_FREQ 5000000 // F_OSC/4
for(i=0;i<n;i++)__delay_ms(10);/*10msをn回繰り返し*/
TIMER0 †
- 4/F_OSC*プリスケーラ設定値 [s]周期で呼ばれる。
疑問 †
- configの説明はいったいどこにあるのか。
- ブラウンアウトリセットとは
- データコードプロテクションとは
- PORTAを直接書き換えてもだめで、RA0などをいじるとOKなのはなぜか。
- _XTAL_FREQを20MHzにしたらむしろ点滅周期が遅くなったのはなぜか。
- Applications/microchip/doc/chipsにconfigの説明が書いてある。
- Cプログラム上で利用可能なピンのディレクティブをどこで調べればいいのか(PORTA, RA0など)。
- simulatorがあるとの噂、どのように利用するのか。
- PWMのactive low, highとは何か。
- timer一つで複数のPWMの駆動ができるということか。
- timerがいろんな所に使われているが併用はできるのか。
Config †