洪嵐峰 發表於 2023-5-2 18:54:19

PIC16F690

製作USB電壓電流顯示器
需要以下零件:

PIC16F690 微控制器
LCD 顯示屏
INA219 電流感測器模組
10K 歐姆電阻器
4.7K 歐姆電阻器
0.1uF 電容
5V 電源
USB 接口
杜邦線和面包板

連接腳位:

連接 INA219 電流感測器模組到 PIC16F690 的 I2C 接口上。模組的 SDA 線連接到 PIC16F690 的 RC4 腳位,SCL 線連接到 RC3 腳位。
連接 LCD 顯示屏到 PIC16F690 的端口 B 上。顯示屏的 RS 引腳連接到 RB0 腳位,E 引腳連接到 RB1 腳位,D4-D7 引腳分別連接到 RB4-RB7 腳位。
在 PIC16F690 的 VDD 和 VSS 腳位間加上 0.1uF 的電容以穩定電源。
連接 10K 歐姆電阻器到 PIC16F690 的 RA5 腳位,作為 USB 電源的檢測引腳。
連接 4.7K 歐姆電阻器到 RA2 腳位,以啟用 PIC16F690 的內部溫度感測器。
程式碼:

以下是 PIC16F690 的範例程式碼,可用於顯示 USB 電源的電壓和電流:


#include <pic16f690.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INA219_ADDRESS 0x40
#define INA219_REG_CONFIG 0x00
#define INA219_REG_SHUNT_VOLTAGE 0x01
#define INA219_REG_BUS_VOLTAGE 0x02
#define INA219_REG_CURRENT 0x04
#define INA219_REG_POWER 0x03
#define INA219_REG_CALIBRATION 0x05
#define INA219_CAL_VALUE 8192
#define INA219_CURRENT_LSB 0.01
#define LCD_RS PORTBbits.RB0
#define LCD_EN PORTBbits.RB1
#define LCD_D4 PORTBbits.RB4
#define LCD_D5 PORTBbits.RB5
#define LCD_D6 PORTBbits.RB6
#define LCD_D7 PORTBbits.RB7
#define LCD_CMD_CLEAR 0x01
#define LCD_CMD_HOME 0x02
#define LCD_CMD_ENTRY_MODE 0
#define LCD_CMD_INIT1 0x33
#define LCD_CMD_INIT2 0x32
#define LCD_CMD_INIT3 0x28
#define LCD_CMD_DISPLAY_ON 0x0C
#define LCD_CMD_CURSOR_OFF 0x0E

int current_mA = 0;
int voltage_mV = 0;

void init();
void lcd_init();
void lcd_command(unsigned char command);
void lcd_char(unsigned char data);
void lcd_string(const char *str);
void delay(unsigned int d);
void i2c_init();
unsigned int i2c_read(unsigned char reg);
void i2c_write(unsigned char reg, unsigned int value);
void read_ina219();
void main() {
init();
while(1) {
read_ina219();
char buffer;
sprintf(buffer, "U=%d.%02dV I=%d.%02dA", voltage_mV/1000, voltage_mV%1000/10, current_mA/1000, current_mA%1000/10);
lcd_command(LCD_CMD_CLEAR);
lcd_string(buffer);
delay(100);
}
}

void init() {
// 設置 I/O 方向和模式
TRISAbits.TRISA2 = 1;
TRISAbits.TRISA5 = 1;
TRISB = 0x00;
ANSEL = 0x00;
ANSELH = 0x00;
OSCCON = 0b01110000;

lcd_init();
i2c_init();
}

void lcd_init() {
lcd_command(LCD_CMD_INIT1);
delay(5);
lcd_command(LCD_CMD_INIT1);
delay(1);
lcd_command(LCD_CMD_INIT1);
lcd_command(LCD_CMD_INIT2);
lcd_command(LCD_CMD_INIT3);
lcd_command(LCD_CMD_DISPLAY_ON);
lcd_command(LCD_CMD_CURSOR_OFF);
lcd_command(LCD_CMD_CLEAR);
}

void lcd_command(unsigned char command) {
LCD_RS = 0;
LCD_EN = 1;
LCD_D4 = (command >> 4) & 0x01;
LCD_D5 = (command >> 5) & 0x01;
LCD_D6 = (command >> 6) & 0x01;
LCD_D7 = (command >> 7) & 0x01;
LCD_EN = 0;
delay(1);
LCD_EN = 1;
LCD_D4 = command & 0x01;
LCD_D5 = (command >> 1) & 0x01;
LCD_D6 = (command >> 2) & 0x01;
LCD_D7 = (command >> 3) & 0x01;
LCD_EN = 0;
delay(1);
}

void lcd_char(unsigned char data) {
LCD_RS = 1;
LCD_EN = 1;
LCD_D4 = (data >> 4) & 0x01;
LCD_D5 = (data >> 5) & 0x01;
LCD_D6 = (data >> 6) & 0x01;
LCD_D7 = (data >> 7) & 0x01;
LCD_EN = 0;
delay(1);
LCD_EN = 1;
LCD_D4 = data & 0x01;
LCD_D5 = (data >> 1) & 0x01;
LCD_D6 = (data >> 2) & 0x01;
LCD_D7 = (data >> 3) & 0x01;
LCD_EN = 0;
delay(1);
}

void lcd_string(const char *str) {
while(*str) {
lcd_char(*str++);
}
}

void delay(unsigned int d) {
while(d--) {
__delay_ms(1);
}
}

void i2c_init() {
SSPSTAT = 0b10000000;
SSPCON = 0b00101000;
SSPADD = 39;
}


void read_ina219() {

i2c_write(0x00, 0b1000000000000111);

unsigned int voltage = i2c_read(0x02);
voltage = (voltage << 8) | i2c_read(0x01);
voltage = voltage >> 3;
voltage_mV = voltage * 4;

unsigned int current = i2c_read(0x04);
current = (current << 8) | i2c_read(0x03);
current_mA = current / 10;
}

void i2c_write(unsigned char reg, unsigned int value) {
SSPCON2bits.SEN = 1;
while(SSPCON2bits.SEN);
SSPBUF = 0b10000000;
while(SSPSTATbits.R_nW);
while(SSPIF == 0);
SSPIF = 0;
SSPBUF = reg;
while(SSPSTATbits.R_nW);
while(SSPIF == 0);
SSPIF = 0;
SSPBUF = value >> 8;
while(SSPSTATbits.R_nW);
while(SSPIF == 0);
SSPIF = 0;
SSPBUF = value & 0xFF;
while(SSPSTATbits.R_nW);
while(SSPIF == 0);
SSPIF = 0;
SSPCON2bits.PEN = 1;
while(SSPCON2bits.PEN);
}

unsigned int i2c_read(unsigned char reg) {
unsigned int value;
SSPCON2bits.SEN = 1;
while(SSPCON2bits.SEN);
SSPBUF = 0b10000000;
while(SSPSTATbits.R_nW);
while(SSPIF == 0);
SSPIF = 0;
SSPBUF = reg;
while(SSPSTATbits.R_nW);
while(SSPIF == 0);
SSPIF = 0;
SSPCON2bits.RSEN = 1;
while(SSPCON2bits.RSEN);
SSPBUF = 0b10000001;
while(SSPSTATbits.R_nW);
while(SSPIF == 0);
SSPIF = 0;
value = SSPBUF;
SSPCON2bits.ACKDT = 0;
SSPCON2bits.ACKEN = 1;
while(SSPCON2bits.ACKEN);
value = (value << 8) | SSPBUF;
SSPCON2bits.PEN = 1;
while(SSPCON2bits.PEN);
return value;
}


void main() {

lcd_init();
i2c_init();

lcd_string("USB Voltage:");
lcd_set_cursor(0, 1);
lcd_string("USB Current:");

while(1) {

read_ina219();

lcd_set_cursor(13, 0);
lcd_string(" ");
lcd_set_cursor(13, 0);
lcd_string(itoa(voltage_mV));
lcd_string("mV");
lcd_set_cursor(13, 1);
lcd_string(" ");
lcd_set_cursor(13, 1);
lcd_string(itoa(current_mA));
lcd_string("mA");
delay(500);
}
}
頁: [1]
查看完整版本: PIC16F690