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

📄 app.c

📁 TinyWorks操作系统。 每个任务占6~10个字节的RAM空间
💻 C
字号:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <stdio.h>
#include "../TinyWorks.h"
#include "../port.h"
#include "../fifo.h"

TW_TCB TaskBatt_tcb;       // 电池充电任务
TW_TCB TaskComm_tcb;       // SPI通讯任务

// 任务堆栈
Stk_t TaskBatt_Stk[100];
Stk_t TaskComm_Stk[100];

// 电压数据缓冲区
volatile u16 MasterPower_Buff[8];
volatile u16 SlavePower_Buff[8];
volatile u16 MasterPower_r;  // 主电源滤波后的AD值
volatile u16 SlavePower_r;   // 备用电源滤波后的AD值
volatile u16 MasterPower;    // 主电源电压,有一位小数
volatile u16 SlavePower;     // 备用电源电压,有一位小数
volatile u8  PowerIndex=0;

// 通讯缓冲区
// rilo: remote inupt local output, remote is host
// roli: remote output local input, remote is host
volatile u8  RILO_Buffer[128];
volatile u8  ROLI_Buffer[128];
fifo_t rilo;
fifo_t roli;

u16 WorkState;        // 主工作状态
u16 InternalState;    // 内部工作状态

void uart0_init(void);
void adc_init(void);
void SPIReadVoltage( void );
void SPISendUARTData( void );
void SPIReceUARTData( void );
void SPIWriteEEPROM( void );
void SPIReadEEPROM( void );
void SPIReadState( void );

void init_hw( void )
{
    DDRB = _BV(0) | _BV(1) | _BV(4);
    PORTB = _BV(1);
    DDRC = _BV(0) | _BV(1) | _BV(2) | _BV(3) | _BV(4) | _BV(5);
    PORTC = _BV(0) | _BV(1) | _BV(2) | _BV(3) | _BV(4) | _BV(5);
    DDRD = _BV(1) | _BV(2) | _BV(3) | _BV(4) | _BV(5) | _BV(6);
    PORTD = _BV(3) | _BV(4) | _BV(5) | _BV(6);

    SPCR = _BV(6) | _BV(7);

    uart0_init();
    adc_init();
}

ISR(SPI_STC_vect)
{
    SPCR = _BV(6);   // 禁止SPI中断
    switch(SPDR)
    {
    case 0x01:    // 读主、备电源电压
        SPIReadVoltage();
        break;
    case 0x02:    // 串口发送数据
        SPISendUARTData();
        break;
    case 0x03:    // 串口接收数据
        SPIReceUARTData();
        break;
    case 0x04:    // 写EEPROM
        SPIWriteEEPROM();
        break;
    case 0x05:    // 读EEPROM
        SPIReadEEPROM();
        break;
    case 0x06:    // 读工作状态
        SPIReadState();
        break;
    default:
        break;
    }
    SPCR = _BV(6) | _BV(7);
    //byte in SPDR has been sent/received
}

void TimerHook( void )
{
    if ((ADMUX&0x0F)== 0x07)
    {
        ADMUX &= ~_BV(0);
    }
    else
    {
        ADMUX |= _BV(0);
    }
    ADCSRA |= _BV(6);
}

ISR(ADC_vect)
{
    volatile u16 value;
    value = ADC;
    if ((ADMUX&0x0F)== 0x07)
    {
        MasterPower_Buff[PowerIndex] = value;
    }
    else
    {
        SlavePower_Buff[PowerIndex] = value;
        PowerIndex ++;
    }
    if (PowerIndex == 8)
    {
        u16 i;
        value = 0;
        for(i=0; i<8; i ++)
        {
            value += MasterPower_Buff[i];
        }
        value >>= 3;
        MasterPower_r = value;
        value = 0;
        for(i=0; i<8; i ++)
        {
            value += SlavePower_Buff[i];
        }
        value >>= 3;
        SlavePower_r = value;
        PowerIndex = 0;
    }
}

void adc_init(void)
{
    ADCSR = 0x00; //disable adc
    ADMUX = 0x47; //select adc input 0
    ACSR  = 0x80;
    ADCSR = 0xCF;
}

void uart0_init(void)
{
    UCSRB = 0x00; //disable while setting baud rate
    UCSRA = 0x02;
    UCSRC = 0x86;
    UBRRL = 0x67; //set baud rate lo
    UBRRH = 0x00; //set baud rate hi
    UCSRB = 0x98;
}

ISR(USART_RXC_vect)
{
    volatile u8 c;
    c = UDR;
    fifo_add(&roli, c);
    fifo_add(&rilo, c);
}

ISR(USART_UDRE_vect)
{
    PORTD |= _BV(2);            // RS485置为发送状态
    if (fifo_dummy(&rilo) == false)
    {
        u16 To=0;
        UCSRB &= ~_BV(5);  // 关发送中断
        sei();
        UCSRA |= ~_BV(6);
        while(!(UCSRA&_BV(6)))
        {
            To ++;
            if (To>1000)
            {
                break;
            }
            wdt_reset();        // 等待数据发送完毕
        }
        PORTD &= ~_BV(2);       // RS485置为输入
        return;
    }
    UDR = fifo_get(&rilo);      // 发送一个字节的数据
}

void test_send( s8 *str )
{
    while(*str)
    {
        fifo_add(&rilo, *str);
        str ++;
    }
    UCSRB |= _BV(5);
}

s8 strt[20];

void TaskBatt( void )
{
    volatile u16 loc_val;
    for(;;)
    {
        cli();
        loc_val = MasterPower_r;
        sei();
        loc_val *= 45;
        loc_val /= 128;
        cli();
        MasterPower = loc_val;
        sei();
        sprintf(strt, "Master Power is %d.%dV\xd\xa", loc_val/10, loc_val%10);
        test_send(strt);
        cli();
        loc_val = SlavePower_r;
        sei();
        loc_val *= 45;
        loc_val /= 128;
        cli();
        SlavePower = loc_val;
        sei();
        sprintf(strt, "Slave Power is %d.%dV\xd\xa", loc_val/10, loc_val%10);
        test_send(strt);
        TWDelay(270);
        PORTD ^= _BV(5);
        wdt_reset();
    }
}

void TaskComm( void )
{
    TIMSK = 0x01;
    PORTD &= ~_BV(2);
    for(;;)
    {
        TWDelay(600);
        PORTD ^= _BV(6);
        wdt_reset();
        if(fifo_dummy(&rilo) == true)
        {
            UCSRB |= _BV(5);
        }

        //        test_send();
    }
}

u8 WaitSPI( u16 TO )
{
    TO <<= 11;    // 按1个循环4条指令计算
    while(TO)
    {
        if (SPSR&_BV(7))
            return true;
        TO --;
    }
    return false;
}

void SPIReadVoltage( void )
{
    volatile u8 loc_reg;
    SPDR = 0x81;   // 返回命令
    if (WaitSPI(8)==false)
        return;
    loc_reg = SPDR;
    SPDR = MasterPower;
    if (WaitSPI(2)==false)
        return;
    loc_reg = SPDR;
    SPDR = MasterPower>>8;
    if (WaitSPI(2)==false)
        return;
    loc_reg = SPDR;
    SPDR = SlavePower;
    if (WaitSPI(2)==false)
        return;
    loc_reg = SPDR;
    SPDR = SlavePower>>8;
}
void SPISendUARTData( void )
{
    volatile u8 loc_reg, loc_loop;
    InternalState |= 0x01;  // 置上发送数据标志
    SPDR = 0x81;   // 返回命令
    if (WaitSPI(8)==false)
        return;
    loc_loop = SPDR;
    SPDR = loc_loop;
    for(;loc_loop!=0; loc_loop--)
    {
        if (WaitSPI(2)==false)
            return;
        loc_reg = SPDR;
        fifo_add(&rilo, loc_reg);
        SPDR = loc_reg;
    }
}
void SPIReceUARTData( void )
{
    volatile u8 loc_reg, loc_loop;
    InternalState |= 0x01;  // 置上发送数据标志
    SPDR = 0x81;   // 返回命令
    if (WaitSPI(8)==false)
        return;
    loc_loop = SPDR;
    if (loc_loop>fifo_len(&roli))   // 没收到那么多的数据
    {
        loc_loop = fifo_len(&roli);
    }
    SPDR = loc_loop;
    for(;loc_loop!=0; loc_loop--)
    {
        if (WaitSPI(2)==false)
            return;
        loc_reg = SPDR;
        SPDR = fifo_get(&roli);
    }
}
void SPIWriteEEPROM( void )
{}
void SPIReadEEPROM( void )
{}
void SPIReadState( void )
{}

int main( void )
{
    asm("cli");

    rilo.len  = 128;
    rilo.in   = 0;
    rilo.out  = 0;
    rilo.buff = RILO_Buffer;
    roli.len  = 128;
    roli.in   = 0;
    roli.out  = 0;
    roli.buff = ROLI_Buffer;

    _delay_ms(100);
    _delay_ms(100);
    _delay_ms(100);
    _delay_ms(100);
    _delay_ms(100);

    wdt_disable();
    init_hw();
    timer0_init();

    TWInit();
    TWCreate(&TaskBatt_tcb, TaskBatt, (Stk_t*)&TaskBatt_Stk[99], 6);
    TWCreate(&TaskComm_tcb, TaskComm, (Stk_t*)&TaskComm_Stk[99], 1);
    wdt_enable(WDTO_2S);
    TWStart();
    return 0;
}

⌨️ 快捷键说明

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