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

📄 hyperbar.c

📁 单片机ATMEL M8 USB监视m8usbmonitor.rar
💻 C
字号:
// Firmware of HyperBar - USB Super Resource Monitor
//
// Compiler:  ICCAVR 6.31A Pro
// Target:    M8
// Crystal:   4.0000Mhz
// Description:
// Receives data packet from the AVR309 USB chip (AT90S2313),
// and converts the data into a form fitting for display.
// This program employs a popular mechanism called scanning
// to simultaneously light up the SMD LED array. Further more,
// a flash of the status LED indicates a successful reception
// of a data packet from the built-in UART.

#include <iom8v.h>
#include <macros.h>

#define SCALER           500
#define DA_SCALER        50
#define UD_SCALER        10
#define RX_BUF_SIZE      5
#define SOP_CHAR         0xBB
#define EOP_CHAR         0xEE

typedef unsigned char byte;

int da_counter;
byte rx_counter;
byte rx_buffer[RX_BUF_SIZE];
byte dataActive;

int ud_counter;
byte bar1_value, bar1_sample;
byte bar2_value, bar2_sample;
byte dots_sample;

void update_samples()
{
  bar1_sample = rx_buffer[1];
  bar2_sample = rx_buffer[2];
  dots_sample = rx_buffer[3];
}

void update_values()
{ 
  // Update values of led array display
  // for enhancing visual effect
  
  ud_counter--;
  
  if (ud_counter <= 0)
  {
    if (bar1_value < bar1_sample)
    {
      bar1_value++;
    }
    else if (bar1_value > bar1_sample)
    {
      bar1_value--;
    }

    if (bar2_value < bar2_sample)
    {
      bar2_value++;
    }
    else if (bar2_value > bar2_sample)
    {
      bar2_value--;
    }
  
    ud_counter = UD_SCALER;
  }
}

void update_status()
{
  // Flash the STATUS LED when data is active
  if (dataActive == 1)
  {
    da_counter = DA_SCALER;
    PORTB &= ~BIT(1);  // Turn off LED
    dataActive = 0;
  }
  else if (da_counter > 0)
  {
    da_counter--;
    if (da_counter <= 0)
    {
      PORTB |= BIT(1);  // Turn on LED
    }
  }
}

void dled_out()
{
  byte shift_num;
  byte led_data;
  byte scan_pos;

  scan_pos = PORTC & 0x1F;
 
  switch (scan_pos)
  {
  case 0x1E:
    shift_num = (bar1_value > 8) ? 8 : bar1_value;
    led_data = ~(0xFF << shift_num);
    break;
  case 0x1D:
    shift_num = (bar1_value <= 8) ? 0 : bar1_value - 8;
    led_data = ~(0xFF << shift_num);
    break;
  case 0x1B:
    shift_num = (bar2_value > 8) ? 8 : bar2_value;
    led_data = ~(0xFF << shift_num);
    break;
  case 0x17:
    shift_num = (bar2_value <= 8) ? 0 : bar2_value - 8;
    led_data = ~(0xFF << shift_num);
    break;
  case 0x0F:  
    led_data = dots_sample;
    break;
  }

  // display
  PORTB = ((led_data & 0x0F) << 2) | (PORTB & 0xC3);
  PORTD = (led_data & 0xF0) | (PORTD & 0x0F);
}

void init_display()
{
  PORTC = 0x1E | (PORTC & 0xE0);
  dled_out();
}

void scan_dled()
{
  byte scan_signal;

  scan_signal = PORTC & 0x1F;
  if (scan_signal == 0x0F)  // leftmost dled, rewind
  {
    scan_signal = 0x1E;
  }
  else
  {
    scan_signal <<= 1;
    scan_signal |= BIT(0);
  }
 
  // Clear segment signal first!
  PORTB = PORTB & 0xC3;
  PORTD = PORTD & 0x0F;
 
  // Scan for next digit
  PORTC = scan_signal | (PORTC & 0xE0);
  dled_out();
}

void port_init()
{
  DDRB  = 0x3F;  // dled segments (D0-D3)
  PORTB = 0x02;  // power indicator
  DDRC  = 0x1F;  // PC0-PC4 for dled scanning
  PORTC = 0x00;
  DDRD  = 0xF0;  // dled segments (D4-D7)
  PORTD = 0x00;
}

//TIMER1 initialize - prescale:8
// WGM: 4) CTC, TOP=OCRnA
// desired value: 1mSec
// actual value:  1.000mSec (0.0%)
void timer1_init()
{
  TCCR1B = 0x00; //stop
  TCNT1 = 0x0000; //setup
  OCR1A = SCALER;
  TCCR1A = 0x00;
  TCCR1B = 0x0A; //start Timer
  TIMSK = 0x10; //enable timer interrupt
}

#pragma interrupt_handler timer1_compa_isr:7
void timer1_compa_isr()
{
  //compare occured TCNT1=OCR1A
  scan_dled();
  update_status();
  update_values();
}

//UART0 initialize
// desired baud rate: 19200
// char size: 8 bit
// parity: Disabled
void uart0_init()
{
  UCSRB = 0x00; //disable while setting baud rate
  UCSRA = 0x00;
  UCSRC = BIT(URSEL) | 0x06;
  UBRR = 12; //set baud rate
  UCSRB = BIT(RXCIE) | BIT(RXEN) | BIT(TXEN);
}

#pragma interrupt_handler uart0_rx_isr:12
void uart0_rx_isr()
{
  byte data, stat;
 
  stat = UCSRA;
  data = UDR;
 
  if (stat & (BIT(FE) | BIT(DOR)))
  {
    rx_counter = 0;  // error occured
  }
  else
  {
    rx_buffer[rx_counter] = data;

    if (rx_counter == 0)
    {
      if (SOP_CHAR == data)  // start of packet
      {
        rx_counter = 1;
      }
    }
    else if (rx_counter == RX_BUF_SIZE - 1)
    {
      if (EOP_CHAR == data)  // end of packet
      {
        dataActive = 1;
        update_samples();
      }             
      rx_counter = 0;
    }
    else
    {
      rx_counter++;
    }
  }     
}

//call this routine to initialize all peripherals
void init_devices()
{
  //stop errant interrupts until set up
  CLI(); //disable all interrupts
  port_init();
  timer1_init();
  uart0_init();

  MCUCR = 0x00;
  GICR  = 0x00;
  SEI(); //re-enable interrupts
  //all peripherals are now initialized
}

void init_vars()
{
  rx_counter = 0;
  dataActive = 0;
  da_counter = 0;
  ud_counter = UD_SCALER;
 
  bar1_value = 0;
  bar2_value = 0;
  bar1_sample = 0;
  bar2_sample = 0;
  dots_sample = 0x00;
}

void main()
{
  init_vars();
  init_devices();
  init_display();
 
  while(1);
}

⌨️ 快捷键说明

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