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

📄 mcu_atmega48_88.c

📁 nrf24z1 代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (failure==0) {
        TWDR = (devadr<<1) | 0x01;                  // 7-bit device address, LSB=1 for read
        TWCR = (1<<TWINT) | (1<<TWEN);              // Start transmission of address
        loop_until_bit_is_set(TWCR,TWINT);          // Wait until the device address has been sent
        if ((TWSR & 0xF8) != 0x40)                  // Test for ACK after device address and r bit
            failure = 5;                            // Device address and r bitfailed
    }
        
    if (failure==0) {
        TWCR = (1<<TWINT) | (1<<TWEN);              // Initiate reception
        loop_until_bit_is_set(TWCR,TWINT);          // Wait until data has been received
        if ((TWSR & 0xF8) != 0x58)                  // Check reception of last byte
            failure = 6;                            // Last byte receptioin failed
        temp = TWDR;                                // Read the actual data
    } 
        
    TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); // Send stop condition regardless of failure
    if (failure != 0) {
        #ifdef DEBUG2W                              // If failure,
            mcu_putchar('R');
            mcu_putchar('[');
            db_puthex(failure);
            mcu_putchar(']');
            mcu_putchar('(');
            db_puthex(adr);
            mcu_putchar(')');
            db_putenter();
        #endif // DEBUG2W
    }

    return temp;                                    // Return read data

} // mcu_2wread


// Write data to 2-wire slave interface of nRF24Z1, this is all MCU specific!
// DOC: Interrupts must be off during this function!
void mcu_2w_write(char devadr, char adr, char data) {
    char failure = 0;                               // No errors have been detected this far

    // Brief explanation of nRF24Z1 2-wire write:
    // Send start condition
    // Send device address with r/_w = 0
    // Send internal register address
    // Send data byte
    // Send stop condition

    TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);     // Send start condition
    loop_until_bit_is_set(TWCR,TWINT);              // Wait until the start condition has been sent
    if ((TWSR & 0xF8) != 0x08)                      // Test for valid start condition
        failure = 1;                                // Start condition failed
            
    if (failure==0) {
        TWDR = (devadr<<1) & 0xFE;                  // 7-bit device address, LSB=0 for write
        TWCR = (1<<TWINT) | (1<<TWEN);              // Start transmission of address
        loop_until_bit_is_set(TWCR,TWINT);          // Wait until the device address has been sent
        if ((TWSR & 0xF8) != 0x18)                  // Test for ACK after device address and _w bit
            failure = 2;                            // Device address with _w bitfailed
    }
        
    if (failure==0) {
        TWDR = adr;                                 // Send internal address of nRF24Z1
        TWCR = (1<<TWINT) | (1<<TWEN);              // Start transmission of address
        loop_until_bit_is_set(TWCR,TWINT);          // Wait until the internal address has been sent
        if ((TWSR & 0xF8) != 0x28)                  // Test for ACK after data = internal address
            failure = 3;                            // Internal address failed
    }
    
    if (failure==0) {
        TWDR = data;                                // Write the actual data
        TWCR = (1<<TWINT) | (1<<TWEN);              // Initiate reception
        loop_until_bit_is_set(TWCR,TWINT);          // Wait until data has been received
        if ((TWSR & 0xF8) != 0x28)                  // Test for ACK after data transfer
            failure = 4;                            // Data transmission failed
    } 
    
    TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);     // Send stop condition regardless of failure
    if (failure != 0) {
        #ifdef DEBUG2W                              // If failure, display debug information
            mcu_putchar('W');
            mcu_putchar('[');
            db_puthex(failure);
            mcu_putchar(']');
            mcu_putchar('(');
            db_puthex(adr);
            mcu_putchar(')');
            db_putenter();
        #endif // DEBUG2W
    }
} // mcu_2wwrite


#ifdef DEBUG

// Sends a single char over the uart
int mcu_putchar(char c) {
    loop_until_bit_is_set(UCSR0A,UDRE0);            // Wait until the send register is empty
    UDR0 = c;                                       // Send char to send register
    return 0;
}


// Halts, then receives a single char from the uart. Immediate echo
int mcu_getchar(void) {
    char c;
    loop_until_bit_is_set(UCSR0A,RXC0);             // Wait untill a char is received
    c = UDR0;                                       // Read char from uart
    mcu_putchar (c);                                // Echo the character   
    return c;
}

 
// Sets up the uart 8 data, 1 stop 
void mcu_uart_init(void) {
    UBRR0H = 0x00;                                  // This register is always 0x00.
    #ifdef MCU_3686                                 // With 3.686MHz,
        UBRR0L = 3;                                 // Set up for 57600 baud
    #endif
    #ifdef MCU_8000                                 // With 8MHz, 
        UBRR0L = 12;                                // Set up for 38400 baud
    #endif
    #ifdef MCU_1000                                 // With 1MHz, 
        UBRR0L = 12;                                // Set up for 4800 baud
    #endif
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);                 // Enable both read and write
    UCSR0C = (3<<UCSZ00);                           // 8 bits data, 1 stop bit
}
#endif // DEBUG


// Read hardware interface and report which button is pressed according to standard table 
// in hpref_defines.h. You only need to support the buttons that are actually used in your application!
// Rewrite for your hardware. Return values are standard button codes 
// from hpref_defines.h
char mcu_buttons(void) {
    #ifdef ATXDEVBOARD  // Code running on STK500 with active low buttons
        if ((PIND&0x80) == 0x00)                    // Check button at PD7
            return BTN_PLAY;
        else if ((PIND&0x40) == 0x00)               // Check button at PD6
            return BTN_VOLDN;
        else if ((PIND&0x20) == 0x00)               // Check button at PD5
            return BTN_VOLUP;
        else if ((PINB&0x04) == 0x00)               // Check button at PB2
            return BTN_SKIPB;
        else if ((PINB&0x02) == 0x00)               // Check button at PB1
            return BTN_SKIPF;
        else if ((PINB&0x01) == 0x00)               // Check button at PB0
            return BTN_STOP;
        else
            return BTN_NOKEY;
    #else           // Code running on ATX Headphone Reference Design with active high buttons
        if ((PIND&0x80) != 0x00)                    // Check button at PD7
            return BTN_PLAY;
        else if ((PIND&0x40) != 0x00)               // Check button at PD6
            return BTN_VOLDN;
        else if ((PIND&0x20) != 0x00)               // Check button at PD5
            return BTN_VOLUP;
        else if ((PINB&0x04) != 0x00)               // Check button at PB2
            return BTN_SKIPB;
        else if ((PINB&0x02) != 0x00)               // Check button at PB1
            return BTN_SKIPF;
        else if ((PINB&0x01) != 0x00)               // Check button at PB0
            return BTN_STOP;
        else
            return BTN_NOKEY;
    #endif
}


#ifdef USELED

// Turn a LED on the ATX on or off. With atmega48 and 88, the LED is located on PC1. 
// On STK500, the LED is active low, reference design has active high LED.
void mcu_atxled(char mode) {
    #ifdef ATXDEVBOARD                              // Code running on STK500 with active low LED
        if (mode == LEDON)
            PORTC &= ~0x02;                         // Set bit 1 of PORTC to 0, active low
        else if (mode == LEDOFF)
            PORTC |= 0x02;                          // Set bit 1 of PORTC to 1, active low
    #else                                           // Code running on headphone reference board with active high LED
        if (mode == LEDON)
            PORTC |= 0x02;                          // Set bit 1 of PORTC to 1, active high
        else if (mode == LEDOFF)
            PORTC &= ~0x02;                         // Set bit 1 of PORTC to 0, active high
    #endif
}
#endif


#ifdef Z1INTERRUPT

// Enable external interrupts from nRF24Z1, active low interrupt on INT0 on PD2
// The MCU pin receiving the interrupt from nRF24Z1 must be edge sensitive. The nRF24Z1 IRQ
// pin may unknown until 0x7F is written to INTSTA. That sets the pin high, and
// a new interrupt may arrive on the edge. Up to one interrupt from the nRF24Z1 may be
// received between calling mcu_z1int_enable() and mcu_z1int_disable();
void mcu_z1int_enable(void) {
    cli();                                          // Setting up interrupts in atomic operation
    EIFR |= 0x01;                                   // Clear interrupt flag before looking for new one datasheet p. 66
    EICRA |= 0x02;                                  // Int on falling edge of INT0 datasheet p. 65
    EIMSK |= 0x01;                                  // Enable INT0 on bit 0 of EIMNSK datasheet p. 66
    sei();                                          // Enable interrupts thereafter
}


// Disable external interrupts from nRF24Z1, active low interrupt on INT0 on PD2
void mcu_z1int_disable(void) {
    cli();                                          // Atomic operation
    EIMSK &= 0xFE;                                  // Disable INT0 ONLY
    sei();                                          // End of atomic operation 
}


// Wait until IRQ line from nRF24Z1 goes high. This is important, as the IRQ line may go low when nRF24Z1 
// has its interrupts enabled. Does not work with power on interrupt!
// Dangerous to have a loop that might turn infinite if nRF24Z1 dies!
void mcu_z1int_clear(void) {                              
    char temp = 0;
    
    while (temp == 0) {                             // Once, and then While INT0 is active:
        z1_singlewrite(INTSTA, 0x7F);               // Clear all interrupt flags in nRF24Z1 to make INT0 inactive
        mcu_wait_ms(2);
        temp = (PIND & 0x04);                       // Check status of INT0 pin
    }
}


// The handler for the nRF24Z1 interrupt does not clear the nRF24Z1 internal interrupt flag! That means
// new nRF24Z1 interrupts may not arrive before the MCU code explicitly enables them. This handler is
// written for programs that sleep until interrupted. Not for programs where normal execution is
// interrupted.
SIGNAL(SIG_INTERRUPT0) { 
    extern char wakeup;
    
    #ifdef DEBUG
        if (wakeup == WAKE_WAIT)                    // Assume that the delay is going to wake up the MCU
            mcu_putchar('w');                       // Indicate that the MCU woke up from a controlled sleep-until-int-or-timeout
        else
            mcu_putchar('z');                       // Indicate that MCU woke up from unexpected interrupt
    #endif
    
    wakeup = WAKE_Z1_INT;                           // Woken by an external interrupt from nRF24Z1
} 

// Check whether or not the nRF24Z1 is currently outputting an interrupt
char mcu_z1int_active(void) {
    if ((PIND & 0x04) == 0x00)                      // INT0 is active low
        return 1;                                   // If the ATX nRF24Z1 is interrupting the MCU, return a true
    else
        return 0;                                   // If it is not, return a false
}
#endif // Z1INTERRUPT


// Toggle the Z1 ATX wakeup pin on DD[1]. On STK500, this functhion has been assigned to PC3
// mcu_init() must define this pin as an output.
void mcu_z1wakeup_pin(void) {
    PORTC |= 0x08;                                  // Set the wakeup pin
    mcu_wait_ms(5);                                 // Give ATX time to wake up!
    PORTC &= ~0x08;                                 // Clear the wakeup pin
    mcu_wait_ms(10);                                // Wait for ATX nRF24Z1 to be ready to accept commands. In some instances this wait will 
}                                                   // be terminated by an interrupt (if enabled) resulting from the ATX powering up

⌨️ 快捷键说明

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