閲覧総計:8389 (本日:1 昨日:0)
PICに液晶ディスプレー(LCD)が接続できる様になると、PICの動いている状態
をビジュアルで確認出来る様になりとても便利です。
PICの細かな動きが数値で確認できる様になり、細かい補正を行う事が可能に
なります。
LCDへの数値表示により、今回はADC値(50-1023)を-50補正しPWMのduty値
(0-973)にするのが良い事の気付きがありました。
機能:可変抵抗器のアナログ値をデジタル変換し、その値でPWMのduty値を変化
させLEDの明るさをなめらかに変更する。また、dutycycle値、duty値をLCDに
表示する。 201
/* A/D値で発光ダイオード(LED)の明るさをPWM機能で変更する * またPWMのduty値をI2C LCDに表示する * PIC16F1827 * XC8 v1.20 * LED:RA2,RA3 * 可変抵抗(10kΩ):RB5 * I2C SDA:SDA1(RB1) pin7 * I2C SCL:SCL1(RB4) pin10 */ #include <xc.h> #pragma config FOSC = INTOSC, WDTE = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF #pragma config PLLEN = OFF, STVREN = OFF, LVP = OFF //__delay_us(), __delay_ms()へのクロック情報の設定 #define _XTAL_FREQ 8000000 //PICのクロックをHzで設定(8MHz) //関数のプロトタイプ宣言 extern void itostring(char digit, unsigned int data, char *buffer); extern unsigned int read_a2d(unsigned char channel); extern void arg_delay_ms(unsigned int x); void i2cByteWrite(char, char, char); // i2c byte送信 void i2cTxData(char); // i2c SSPBUF セット void LCD_dat(char); // 1文字表示 void LCD_cmd(char); // コマンド出力 void LCD_clr(void); // 全消去 void LCD_int(void); // 初期化 void LCD_str(char *); // 文字列表示 void LCD_ROMstr(const char *); // ROM文字列表示 void LCD_posyx(char,char); // カーソル位置指定 void LCD_hex(char); // 16進文字変換表示 int main(void) { //使用変数の定義 unsigned int adc_val; //ADC値の結果(0-1023) unsigned int dutycycle; //PWM duty(0〜1000) unsigned char s_dutycycle[6]; //LCD表示用文字列 unsigned int duty; //duty%値 unsigned char s_duty[6]; //LCD表示用文字列 //PICの初期設定 PORTA = 0b00000000; //PORTAの中身をきれいにする PORTB = 0b00000000; //PORTBの中身をきれいにする TRISA = 0b00000000; //PORTA全てを0:出力に設定 TRISB = 0b11111111; //PORTBは全て1:入力に設定 ANSELA = 0b00000000; //RA4(AN4)-RA0(AN0)は全て0:デジタルI/Oとする ANSELB = 0b00100000; //RB5(AN7)のみ1:アナログ、他は0:デジタルI/Oとする OSCCON = 0b01110000; //PLL:OFF, 内部クロック8MHzで駆動 OPTION_REGbits.nWPUEN = 0; // 0:PORTB内部プルアップ利用に設定 WPUBbits.WPUB1 = 1; // RB1をI2C通信のウィークプルアップ WPUBbits.WPUB4 = 1; // RB4をI2C通信のウィークプルアップ //CCP3(RA3)へPWM信号を出力(Timer2使用) //PWM各種設定値の計算 //クロック8MHz Tosc = 0.125μsの時 //2000HzのPWM信号を発信する場合 // //周期 = 2000Hz = 1/2000 = 500μs //(PR2の範囲は0〜255) //Timer2のプリスケール 4 //周期 = (PR2 + 1) * 4 * Tosc * (Timer2のプリスケール値)であるから //PR2 = (周期 / (4 * Tosc * (Timer2のプリスケール値)) - 1 //PR2 = (500 / (4 * 0.125 * 4)) - 1 //PR2 = 249 // //PWM分解能 DC1(Max)は //duty = DC1 * Tosc * (Timer2のプリスケール値)であるから //DC1 = duty / (Tosc * (Timer2のプリスケール値)) //DC1(Max) = 500 / (0.125 * 4) //DC1(Max) = 1000 //PWM各種条件設定 //CCP3(RA3)へPWM信号を出力 CCPTMRS = 0b00000000; //CCP3はTimer2使用に設定 CCP3CON = 0b00001100; //PWMモードを使用する T2CON = 0b00000001; ////プリスケール 4に設定 PR2 = 249; //PWM周波数2000Hzに設定 TMR2 = 0; //Timer2カウンターをクリアー T2CONbits.TMR2ON = 1; //Timer2 ON //I2C通信の初期設定 SSPCON1 = 0b00101000; // I2Cマスターモード指定 SSPSTAT = 0b00000000; // I2C STATUSの設定 SSPADD = 19; // I2Cクロック周波数100KHz(=(19+1)*4/8MHz) //A2D変換開始 ADCON1 = 0b10010000; //select right justify result, ADCS Fosc/8, A/D port configuratio n 0 ADCON0bits.ADON = 1; //ADON //メイン処理 LATAbits.LATA2 = 1; //RA2:パワーオンを示すLED点灯(かつ照度比較用LED) LCD_int(); // LCD初期化 LCD_ROMstr("duty val ="); // 1行目に表示 LCD_posyx(1,0); // 2行目頭にカーソル移動 LCD_ROMstr("duty% ="); while(1) { //アナログデータの取得 10bit(0~1023) adc_val = read_a2d(7); //RB5(AN7)のアナログ値読み込み dutycycle = adc_val - 50; //ADC値をdutyに入力 -50は補正値 //CCP3のdutycycle変更(LEDの明るさが変化する) //解像度10ビットのうち上位8ビットをCCPR3Lレジスタに格納 CCPR3L = dutycycle >> 2; //解像度10ビットのうち下位2ビットをCCP3CONレジスタの4,5ビットへ格納 CCP3CON |= (dutycycle & 0x0003) << 4; //duty値のLCD表示 itostring(4, dutycycle, s_dutycycle); //数値の文字列への変換 LCD_posyx(0,12); // 1行9文字目にカーソル移動 LCD_str(s_dutycycle); duty = (dutycycle +5) / 10; //+5は四捨五入処理 itostring(3, duty, s_duty); //数値の文字列への変換 LCD_posyx(1,8); // 2行8文字目にカーソル移動 LCD_str(s_duty); //duty%値の表示 LCD_posyx(1,11); // 2行11文字目にカーソル移動 LCD_ROMstr("%"); } }
★この情報は役に立ちましたか?