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

📄 avr.cpp

📁 plc软件的源代码 支持PIC ATMEGA单片机
💻 CPP
📖 第 1 页 / 共 4 页
字号:
                IfBitSet(REG_EECR, 1);
                Instruction(OP_RJMP, isBusy, 0);

                IfBitClear(EepromHighByteWaitingAddr, EepromHighByteWaitingBit);
                Instruction(OP_RJMP, done, 0);

                // Just increment EEARH:EEARL, to point to the high byte of
                // whatever we just wrote the low byte for.
                LoadXAddr(REG_EEARL);
                Instruction(OP_LD_X, 16, 0);
                LoadXAddr(REG_EEARH);
                Instruction(OP_LD_X, 17, 0);
                Instruction(OP_INC, 16, 0);
                DWORD noCarry = AllocFwdAddr();
                Instruction(OP_BRNE, noCarry, 0);
                Instruction(OP_INC, 17, 0);
                FwdAddrIsNow(noCarry);
                // X is still REG_EEARH
                Instruction(OP_ST_X, 17, 0);
                LoadXAddr(REG_EEARL);
                Instruction(OP_ST_X, 16, 0);

                LoadXAddr(EepromHighByte);
                Instruction(OP_LD_X, 16, 0);
                LoadXAddr(REG_EEDR);
                Instruction(OP_ST_X, 16, 0);
                LoadXAddr(REG_EECR);
                Instruction(OP_LDI, 16, 0x04);
                Instruction(OP_ST_X, 16, 0);
                Instruction(OP_LDI, 16, 0x06);
                Instruction(OP_ST_X, 16, 0);

                ClearBit(EepromHighByteWaitingAddr, EepromHighByteWaitingBit);

                FwdAddrIsNow(isBusy);
                SetBit(addr, bit);
                FwdAddrIsNow(done);
                break;
            }
            case INT_EEPROM_READ: {
                MemForVariable(a->name1, &addrl, &addrh);
                int i;
                for(i = 0; i < 2; i++) {
                    WriteMemory(REG_EEARH, ((a->literal+i) >> 8));
                    WriteMemory(REG_EEARL, ((a->literal+i) & 0xff));
                    WriteMemory(REG_EECR, 0x01);
                    LoadXAddr(REG_EEDR);
                    Instruction(OP_LD_X, 16, 0);
                    if(i == 0) {
                        LoadXAddr(addrl);
                    } else {
                        LoadXAddr(addrh);
                    }
                    Instruction(OP_ST_X, 16, 0);
                }
                break;
            }
            case INT_EEPROM_WRITE:
                MemForVariable(a->name1, &addrl, &addrh);
                SetBit(EepromHighByteWaitingAddr, EepromHighByteWaitingBit);
                LoadXAddr(addrh);
                Instruction(OP_LD_X, 16, 0);
                LoadXAddr(EepromHighByte);
                Instruction(OP_ST_X, 16, 0);

                WriteMemory(REG_EEARH, (a->literal >> 8));
                WriteMemory(REG_EEARL, (a->literal & 0xff));
                LoadXAddr(addrl);
                Instruction(OP_LD_X, 16, 0);
                LoadXAddr(REG_EEDR);
                Instruction(OP_ST_X, 16, 0);
                LoadXAddr(REG_EECR);
                Instruction(OP_LDI, 16, 0x04);
                Instruction(OP_ST_X, 16, 0);
                Instruction(OP_LDI, 16, 0x06);
                Instruction(OP_ST_X, 16, 0);
                break;
            
            case INT_READ_ADC: {
                MemForVariable(a->name1, &addrl, &addrh);

                WriteMemory(REG_ADMUX, 
                    (0 << 6) |              // AREF, internal Vref odd
                    (0 << 5) |              // right-adjusted
                    MuxForAdcVariable(a->name1));

                // target something around 200 kHz for the ADC clock, for
                // 25/(200k) or 125 us conversion time, reasonable
                int divisor = (Prog.mcuClock / 200000);
                int j = 0;
                for(j = 1; j <= 7; j++) {
                    if((1 << j) > divisor) break;
                }

                BYTE adcsra = 
                    (1 << 7) |              // ADC enabled
                    (0 << 5) |              // not free running
                    (0 << 3) |              // no interrupt enabled
                    j;                      // prescaler setup
            
                WriteMemory(REG_ADCSRA, adcsra);
                WriteMemory(REG_ADCSRA, (BYTE)(adcsra | (1 << 6)));

                DWORD waitForFinsh = AvrProgWriteP;
                IfBitSet(REG_ADCSRA, 6);
                Instruction(OP_RJMP, waitForFinsh, 0);

                LoadXAddr(REG_ADCL);
                Instruction(OP_LD_X, 16, 0);
                LoadXAddr(addrl);
                Instruction(OP_ST_X, 16, 0);

                LoadXAddr(REG_ADCH);
                Instruction(OP_LD_X, 16, 0);
                LoadXAddr(addrh);
                Instruction(OP_ST_X, 16, 0);

                break;
            }
            case INT_UART_SEND: {
                MemForVariable(a->name1, &addrl, &addrh);
                MemForSingleBit(a->name2, TRUE, &addr, &bit);

                DWORD noSend = AllocFwdAddr();
                IfBitClear(addr, bit);
                Instruction(OP_RJMP, noSend, 0);

                SetBit(REG_UCSRA, 6); // write 1 to clear bit
                LoadXAddr(addrl);
                Instruction(OP_LD_X, 16, 0);
                LoadXAddr(REG_UDR);
                Instruction(OP_ST_X, 16, 0);

                FwdAddrIsNow(noSend);
                ClearBit(addr, bit);

                DWORD dontSet = AllocFwdAddr();
                IfBitSet(REG_UCSRA, 6);
                Instruction(OP_RJMP, dontSet, 0);
                SetBit(addr, bit);
                FwdAddrIsNow(dontSet);

                break;
            }
            case INT_UART_RECV: {
                MemForVariable(a->name1, &addrl, &addrh);
                MemForSingleBit(a->name2, TRUE, &addr, &bit);
        
                ClearBit(addr, bit);

                DWORD noChar = AllocFwdAddr();
                IfBitClear(REG_UCSRA, 7);
                Instruction(OP_RJMP, noChar, 0);

                SetBit(addr, bit);
                LoadXAddr(REG_UDR);
                Instruction(OP_LD_X, 16, 0);
                LoadXAddr(addrl);
                Instruction(OP_ST_X, 16, 0);
                
                LoadXAddr(addrh);
                Instruction(OP_LDI, 16, 0);
                Instruction(OP_ST_X, 16, 0);

                FwdAddrIsNow(noChar);
                break;
            }
            case INT_END_IF:
            case INT_ELSE:
                return;

            case INT_SIMULATE_NODE_STATE:
            case INT_COMMENT:
                break;

            default:
                oops();
                break;
        }
    }
}

//-----------------------------------------------------------------------------
// 16x16 signed multiply, code from Atmel app note AVR200. op1 in r17:16,
// op2 in r19:18, result low word goes into r19:18.
//-----------------------------------------------------------------------------
static void MultiplyRoutine(void)
{
    FwdAddrIsNow(MultiplyAddress);

    DWORD m16s_1;
    DWORD m16s_2 = AllocFwdAddr();

    Instruction(OP_SUB, 21, 21);
    Instruction(OP_SUB, 20, 20);
    Instruction(OP_LDI, 22, 16);
    m16s_1 = AvrProgWriteP; Instruction(OP_BRCC, m16s_2, 0);
    Instruction(OP_ADD, 20, 16);
    Instruction(OP_ADC, 21, 17);
    FwdAddrIsNow(m16s_2); Instruction(OP_SBRC, 18, 0);
    Instruction(OP_SUB, 20, 16);
    Instruction(OP_SBRC, 18, 0);
    Instruction(OP_SBC, 21, 17);
    Instruction(OP_ASR, 21, 0);
    Instruction(OP_ROR, 20, 0);
    Instruction(OP_ROR, 19, 0);
    Instruction(OP_ROR, 18, 0);
    Instruction(OP_DEC, 22, 0);
    Instruction(OP_BRNE, m16s_1, 0);
    Instruction(OP_RET, 0, 0);
}

//-----------------------------------------------------------------------------
// 16/16 signed divide, code from the same app note. Dividend in r17:16,
// divisor in r19:18, result goes in r17:16 (and remainder in r15:14).
//-----------------------------------------------------------------------------
static void DivideRoutine(void)
{
    FwdAddrIsNow(DivideAddress);

    DWORD d16s_1 = AllocFwdAddr();
    DWORD d16s_2 = AllocFwdAddr();
    DWORD d16s_3;
    DWORD d16s_4 = AllocFwdAddr();
    DWORD d16s_5 = AllocFwdAddr();
    DWORD d16s_6 = AllocFwdAddr();

    Instruction(OP_MOV, 13, 17);
    Instruction(OP_EOR, 13, 19);
    Instruction(OP_SBRS, 17, 7);
    Instruction(OP_RJMP, d16s_1, 0);
    Instruction(OP_COM, 17, 0);
    Instruction(OP_COM, 16, 0);
    Instruction(OP_SUBI, 16, 0xff);
    Instruction(OP_SBCI, 17, 0xff);
    FwdAddrIsNow(d16s_1); Instruction(OP_SBRS, 19, 7);
    Instruction(OP_RJMP, d16s_2, 0);
    Instruction(OP_COM, 19, 0);
    Instruction(OP_COM, 18, 0);
    Instruction(OP_SUBI, 18, 0xff);
    Instruction(OP_SBCI, 19, 0xff);
    FwdAddrIsNow(d16s_2); Instruction(OP_EOR, 14, 14);
    Instruction(OP_SUB, 15, 15);
    Instruction(OP_LDI, 20, 17);

    d16s_3 = AvrProgWriteP; Instruction(OP_ADC, 16, 16);
    Instruction(OP_ADC, 17, 17);
    Instruction(OP_DEC, 20, 0);
    Instruction(OP_BRNE, d16s_5, 0);
    Instruction(OP_SBRS, 13, 7);
    Instruction(OP_RJMP, d16s_4, 0);
    Instruction(OP_COM, 17, 0);
    Instruction(OP_COM, 16, 0);
    Instruction(OP_SUBI, 16, 0xff);
    Instruction(OP_SBCI, 17, 0xff);
    FwdAddrIsNow(d16s_4); Instruction(OP_RET, 0, 0);
    FwdAddrIsNow(d16s_5); Instruction(OP_ADC, 14, 14);
    Instruction(OP_ADC, 15, 15);
    Instruction(OP_SUB, 14, 18);
    Instruction(OP_SBC, 15, 19);
    Instruction(OP_BRCC, d16s_6, 0);
    Instruction(OP_ADD, 14, 18);
    Instruction(OP_ADC, 15, 19);
    Instruction(OP_CLC, 0, 0);
    Instruction(OP_RJMP, d16s_3, 0);
    FwdAddrIsNow(d16s_6); Instruction(OP_SEC, 0, 0);
    Instruction(OP_RJMP, d16s_3, 0);
}

//-----------------------------------------------------------------------------
// Compile the program to REG code for the currently selected processor
// and write it to the given file. Produce an error message if we cannot
// write to the file, or if there is something inconsistent about the
// program.
//-----------------------------------------------------------------------------
void CompileAvr(char *outFile)
{
    FILE *f = fopen(outFile, "w");
    if(!f) {
        Error(_("Couldn't open file '%s'"), outFile);
        return;
    }

    if(setjmp(CompileErrorBuf) != 0) {
        fclose(f);
        return;
    }

    // Here we must set up the addresses of some registers that for some
    // stupid reason move around from AVR to AVR.
    if(strcmp(Prog.mcu->mcuName, "Atmel AVR ATmega16 40-PDIP")==0  ||
       strcmp(Prog.mcu->mcuName, "Atmel AVR ATmega32 40-PDIP")==0 ||
       strcmp(Prog.mcu->mcuName, "Atmel AVR ATmega162 40-PDIP")==0 ||
       strcmp(Prog.mcu->mcuName, "Atmel AVR ATmega8 28-PDIP")==0)
    {
        REG_TIMSK = 0x59;
        REG_TIFR = 0x58;
        REG_UBRRH = 0x40;
        REG_UBRRL = 0x29;
        REG_UCSRB = 0x2a;
        REG_UCSRA = 0x2b;
        REG_UDR = 0x2c;
    } else {
        REG_TIMSK = 0x57;
        REG_TIFR = 0x56;
        REG_UBRRH = 0x98;
        REG_UBRRL = 0x99;
        REG_UCSRB = 0x9a;
        REG_UCSRA = 0x9b;
        REG_UDR = 0x9c;
    }

    WipeMemory();
    MultiplyUsed = FALSE;
    MultiplyAddress = AllocFwdAddr();
    DivideUsed = FALSE;
    DivideAddress = AllocFwdAddr();
    AllocStart();

    // Where we hold the high byte to program in EEPROM while the low byte
    // programs.
    EepromHighByte = AllocOctetRam();
    AllocBitRam(&EepromHighByteWaitingAddr, &EepromHighByteWaitingBit);

    WriteRuntime();
    IntPc = 0;
    CompileFromIntermediate();

    if(Prog.mcu->avrUseIjmp) {
        Instruction(OP_LDI, 30, (BeginningOfCycleAddr & 0xff));
        Instruction(OP_LDI, 31, (BeginningOfCycleAddr >> 8));
        Instruction(OP_IJMP, 0, 0);
    } else {
        Instruction(OP_RJMP, BeginningOfCycleAddr, 0);
    }

    MemCheckForErrorsPostCompile();

    if(MultiplyUsed) MultiplyRoutine();
    if(DivideUsed) DivideRoutine();

    WriteHexFile(f);
    fclose(f);

    char str[MAX_PATH+500];
    sprintf(str, _("Compile successful; wrote IHEX for AVR to '%s'.\r\n\r\n"
        "Remember to set the processor configuration (fuses) correctly. "
        "This does not happen automatically."), outFile);
    CompileSuccessfulMessage(str);
}

⌨️ 快捷键说明

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