⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 charger.c

📁 基于AVR制作的电话语音录制系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* [KSC4]-------------------------------------------------------------------[]
 *
 *  CHARGER.C - NiMH Battery Charger for ATTiny45, version 1.0
 *              Part of Entry AT3344 for the Atmel Design Contest 2006
 *
 * []-----------------------------------------------------------------------[]
 */

#include <avr/io.h>			// include I/O defs (port names, pin names, etc)
#include <avr/interrupt.h>	// include interrupt support
#include <avr/sleep.h>
#include <avr/pgmspace.h>

/* ------------------------- Configuration Macros ------------------------- */

/* Enable sending debug messages over the serial port */

#define BATT_DEBUG

// ---- Basic Hardware Configuration

/* CPU Clock */

#define F_CPU             2000000L

/* Which ADC channels/MCU Pins are used to measure the battery and mains
   voltages. They're usually connected to a resistor network voltage divider
   to make the voltage range acceptable to the ADC. For instance, the resistor
   values are 220k/100k, making the range 9-16V appear as 2.81-5.00V  */

#define ADC_BATTERY_CHANNEL      3
#define ADC_MAIN_POWER_CHANNEL   2

/* Which pin will act as the serial TXD (transmit data) where the logging/
   debugging messages will be sent to. */

#define SERIAL_OUT_DDR        DDRB
#define SERIAL_OUT_PORT      PORTB
#define SERIAL_OUT_BIT         PB1

/* Which pin is connected to the charger enable function. In this project,
   when pulled *down* it enables an LM317-based  constant-current regulator
   that recharges the battery. This enable port has a resistor pullup, so it's
   disabled by default even if the MCU is dead. */

#define BATTERY_CHARGER_DDR   DDRB
#define BATTERY_CHARGER_PORT PORTB
#define BATTERY_CHARGER_BIT    PB0

/* Serial transmission stuff -- basic speed, phase (speed multiplier -- was
   needed for reception, but I have removed the reception code) and
   appropriate calculations for the timer comparator */

#define BAUD_RATE             1200
#define PHASE                    4
#define TIMER0_PRESCALER         8

#define PHASE_MASK               (PHASE-1)
#define TIMER0_TOP               (F_CPU/TIMER0_PRESCALER/PHASE/BAUD_RATE)

/* Serial Transmit Fifo size. Bytes to be transmitted are first put in here
   then transmitted later */

#define TXFIFOSIZE              80

#if TIMER0_TOP > 255
#error TIMER0_TOP too large for this baud rate, increase PHASE
#endif

/* ---------------- Utility Macros & Macro-Defined Functions -------------- */

#define TRUE                     1
#define FALSE                    0

/* Macros for better readability of Analog-to-Digital Converter operations */

#define adc_enable()         (ADCSRA |= _BV(ADEN))
#define adc_busy()           (ADCSRA & _BV(ADSC))
#define adc_start()          ADCSRA |= _BV(ADSC)
#define adc_set_channel(c)   \
    (ADMUX = ((ADMUX & ~(_BV(MUX3)|_BV(MUX2)|_BV(MUX1)|_BV(MUX0))) \
	|((c)<<MUX0)))
#define adc_value()          (ADCL|((ADCH & 3)<<8))
#define adc_set_prescaler(v) (ADCSRA = (ADCSRA & 0xF8) | (v))
#define adc_set_reference(v) (ADMUX = (ADMUX & 0x4F) | (((v)&4)<<2) | \
                                                       (((v)&3)<<6) )
#define ADC_CHANNELS          4

#define ADC_CH_0              0
#define ADC_CH_1              1
#define ADC_CH_2              2
#define ADC_CH_3              3
#define ADC_CH_2DIFF2_1X      4
#define ADC_CH_2DIFF2_20X     5
#define ADC_CH_2DIFF3_1X      6
#define ADC_CH_2DIFF3_20X     7
#define ADC_CH_TEMP_SENSOR   15
#define ADC_PS_CLK_4          2
#define ADC_PS_CLK_8          3
#define ADC_PS_CLK_16         4
#define ADC_REF_VCC_DISC      0
#define ADC_REF_1_1V_DISC     2
#define ADC_REF_2_56V_DISC    6

/* ----------------------- Global Variables & Declarations ---------------- */

volatile enum BatteryChargingState {
    BatteryNotCharging,
    BatteryInitialSense,  BatterySoftCharging,
	BatteryFastCharging, BatteryTrickleCharging
} charging_state;

unsigned  char max_battery_charge_time;
short last_voltage,voltage;
unsigned char quell_charging;
unsigned short duty_cycle;
unsigned  long avg_accum;

volatile unsigned char fifo[TXFIFOSIZE];
volatile unsigned char txhead,txtail;
volatile unsigned char xmitbyte,xmitbit,phase;
volatile unsigned short cnt;

volatile unsigned short gcount;
volatile unsigned char  has_new_second;
volatile unsigned char  hours,minutes,seconds;

/* --------------------------- Function Prototypes ------------------------ */

void xmit(unsigned char c);
void xmit_crlf(void);
void xmit_timestamp(void);
void xmit_u8as2d(unsigned char val);
void xmit_str_p(const prog_char *p);
void do_charge_control(void);
unsigned short getVoltage(unsigned char ch);
void xmit_k1_u8as5dot2f(unsigned short val);

/* ------------------------- Macro-Defined Functions ---------------------- */

/* Conveniente macros to have the ADC measure battery and mains voltages.
   'Mains' refers to the 12-18VDC input to the circuit after the power brick,
   not the 110-240VAC from the outlet. */

#define get_battery_voltage() getVoltage(ADC_BATTERY_CHANNEL)
#define get_mains_voltage()   getVoltage(ADC_MAIN_POWER_CHANNEL)

/* Macros to transmit a zero or one bit over the serial port */

#define xmit0()               SERIAL_OUT_PORT &= ~_BV(SERIAL_OUT_BIT)
#define xmit1()               SERIAL_OUT_PORT |=  _BV(SERIAL_OUT_BIT)

/* Looks like it's reversed, but it is not. The hardware works in such a
   way that the charger is disabled when the pin is high */

#define disable_charger()     BATTERY_CHARGER_PORT |=  _BV(BATTERY_CHARGER_BIT)
#define enable_charger()      BATTERY_CHARGER_PORT &= ~_BV(BATTERY_CHARGER_BIT)

/* Sets the battery charger 1Hz PWM duty cycle, which controls the 'strength'
   of the charging operation */

#define set_duty_cycle(x)     (duty_cycle=((100-(x))/100.0*BAUD_RATE))

/* Helper macro to automatically define a string in program space and have
   it transmitted */

#define xmit_pstr(x)          xmit_str_p(PSTR(x))

/* ------------------------------ Main Program ---------------------------- */

int main(void)
{		
    // Set the main clock prescaler to BASE_CLOCK/4, yielding 2.0MHz
    // for the CPU clock
    
    CLKPR = 0x80;
    CLKPR = 2;

    SERIAL_OUT_DDR      |= _BV(SERIAL_OUT_BIT);
    BATTERY_CHARGER_DDR |= _BV(BATTERY_CHARGER_BIT);
	TCCR0A = 2;
    
#if TIMER0_PRESCALER == 8
    TCCR0B = 2;
#else
	TCCR0B = 1;
#endif

	OCR0A  = TIMER0_TOP;
	TIMSK  = _BV(OCIE0A);
    
    adc_set_prescaler(ADC_PS_CLK_16);
    adc_set_reference(ADC_REF_VCC_DISC);
    adc_enable();
    
    disable_charger();
    set_duty_cycle(0);

	sei();
    xmit_pstr("\r\n\r\nWelcome to AT3344's Battery Charger "
              "Monitor/Debug Facility v1.0\r\n\r\n");
    for (;;) {
        if (has_new_second) {
            has_new_second=FALSE;
            do_charge_control();
            //xmit_timestamp(); xmit_crlf();
        }
    }
}

/* Transmits a line break */

void xmit_crlf(void)
{
    xmit(13); xmit(10);
}

/* Transmits the current time */

void xmit_timestamp(void)
{
    xmit_u8as2d(hours);
    xmit(':');
    xmit_u8as2d(minutes);
    xmit(':');
    xmit_u8as2d(seconds);
}

/*  Converts 'val' to a 2-digit decimal number and transmits it. If the
    value is larger than 2 digits, transmits four '#'-signs instead to
    flag overflow */

void xmit_u8as2d(unsigned char val) 
{
    unsigned char c;
    if (val<100) {
        c=val/10;
        c+='0'; xmit(c);
        c=val%10+'0';
        xmit(c);
    } else {
        xmit('#'); xmit('#');
    }
}

/*  Converts 'val' to a 4-digit decimal number and transmits it. If the
    value is larger than 4 digits, transmits four '#'-signs instead to
    flag overflow */

void xmit_u8as4d(unsigned short val)
{
   if (val<10000) {
       xmit_u8as2d(val/100);
       xmit_u8as2d(val%100);
    } else {
       xmit('#'); xmit('#');
       xmit('#'); xmit('#');
    }
}

/* Converts 'val' (an averaged voltage from the 'do_charger_control' function
   further down) to millivolts and the prints it as a fixed-point value
   XX.XX in volts. It is used when debugging to log the battery voltage */

void xmit_k1_u8as5dot2f(unsigned short val)
{
    /* This essentially multiplies by 1.953125, which is the correct
       conversion factor from ADC units to millivolts, considering
       the ADC reference voltage of 5V, the x8 scaling due to averaging
       and the 220k/110kohm voltage divider where the ADC is connected. 
       Change the hardware and you'll have to change this. The bit gymnastics
       is just to avoid needing floating point stuff that would make the
       resulting object code so much larger. */
    unsigned short v=(val<<1)-(val>>4)+(val>>6);
    xmit_u8as2d(v/1000);
    xmit('.');
    xmit_u8as2d((v%1000)/10);
}

/* Transmits a zero-terminated string pointed by 'p' in program space (the
   MCU internal flash memory). Used in conjunction witht eh xmit_pstr macro
   for convenient use. */

void xmit_str_p(const prog_char *p)
{
    unsigned char c;
    for (;;) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -