├── README.md ├── t1614_led.cpp ├── t1614_timerA.cpp ├── t1614_spi_slave.cpp ├── LICENSE ├── t1614_timerB.cpp ├── t1614_adc.cpp ├── t1614_usart.cpp ├── t1614_spi_master.cpp ├── t1614_rtc.cpp └── t1614_twi.cpp /README.md: -------------------------------------------------------------------------------- 1 | # attiny1614example 2 | Code Examples for ATtiny1614(Microchip's AVR) 3 | 4 | ・TWI(I2C) 5 | ・USART 6 | ・SPI(master/slave) 7 | ・TCA(16bit Timer TypeA) 8 | ・TCB(16bit Timer TypeB) 9 | ・RTC(Real Time Clock with Xtal) 10 | ・ADC(Analog/Digital Converter) 11 | ・LED(Digital I/O) 12 | 13 | # License 14 | 15 | [Unlicense](http://unlicense.org/) 16 | -------------------------------------------------------------------------------- /t1614_led.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * t1614_led.cpp 3 | * 4 | * Created: 2018/11/03 5 | * Author : chromia 6 | */ 7 | 8 | #include 9 | #define F_CPU 3333333 /* 20MHz / 6(default prescale) */ 10 | #include 11 | 12 | /* Pin Assign 13 | * 7.PB2 : LED output 14 | */ 15 | #define LED_bp 2 //PB2 16 | #define LED_bm (1< 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | /* PIN Assign 12 | * 9.PB0 : LED 13 | */ 14 | 15 | #define PIN_LED_bp 0 // PB0 16 | #define PIN_LED_bm (1 << PIN_LED_bp) 17 | 18 | /* 1sec-interval LED blinking by TCA(Normal Mode) 19 | * Attiny1614's default clock is 20MHz(RC) 20 | * CLK_PER is 3.333MHz ( default prescaler rate is 6, then 20/6 == 3.3 ) 21 | * 22 | * TCA's freq = CLK_PER / (2*N*COMPARE) 23 | * N is prescaler rate (1,2,4,8,16,64,256,1024) 24 | * if N=64, COMPARE = 26042 (3333333 / 2*64*26042 = 0.999987 [sec]) -> 1Hz 25 | */ 26 | #define COMPARE 26042 27 | 28 | int main(void) 29 | { 30 | // LED 31 | PORTB.DIRSET = PIN_LED_bm; 32 | 33 | // TCA 34 | TCA0.SINGLE.CTRLB = 35 | TCA_SINGLE_CMP0EN_bm | // Enables Compare Channel 0 (output port WO0 = PB0) 36 | TCA_SINGLE_WGMODE_FRQ_gc; // FRQ Waveform Generation 37 | TCA0.SINGLE.CMP0 = COMPARE; 38 | TCA0.SINGLE.CTRLA = 39 | TCA_SINGLE_CLKSEL_DIV64_gc | // N=64 40 | TCA_SINGLE_ENABLE_bm; // Start 41 | 42 | while (1) 43 | { 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /t1614_spi_slave.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * t1614_spi_slave.cpp 3 | * 4 | * Created: 2018/11/10 5 | * Author : chromia 6 | */ 7 | 8 | #include 9 | 10 | /* SPI as Slave 11 | * Pin Assign 12 | * 2. PA4 : SS 13 | * 11.PA1 : MOSI 14 | * 12.PA2 : MISO 15 | * 13.PA3 : SCK 16 | */ 17 | #define MOSI_bp 1 18 | #define MOSI_bm (1 << MOSI_bp) 19 | #define MISO_bp 2 20 | #define MISO_bm (1 << MISO_bp) 21 | #define SCK_bp 3 22 | #define SCK_bm (1 << SCK_bp) 23 | #define SS_bp 4 24 | #define SS_bm (1 << SS_bp) 25 | 26 | #define DUMMY 0xFF 27 | 28 | int main(void) 29 | { 30 | // Port I/O Configuration 31 | PORTA.DIRSET = MISO_bm; // Output:MISO Input:MOSI/SCK/SS 32 | 33 | // SPI Configuration 34 | SPI0.CTRLB = 35 | SPI_MODE_2_gc; // Mode2 36 | SPI0.CTRLA = 37 | !SPI_MASTER_bm | // as Slave 38 | SPI_ENABLE_bm; // Start 39 | 40 | /* Simple count-up responder */ 41 | while (1) 42 | { 43 | if(SPI0.INTFLAGS & SPI_RXCIF_bm){ 44 | uint8_t count = SPI0.DATA; //read received data 45 | if(count != DUMMY){ 46 | count++; // count up 47 | SPI0.DATA = count; // respond to master 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /t1614_timerB.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * t1614_timerB.cpp 3 | * 4 | * Created: 2018/10/25 5 | * Author : chromia 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | /* PIN Assign 12 | * 5.PA7 : LED 13 | */ 14 | 15 | #define PIN_LED_bp 7 // PA7 16 | #define PIN_LED_bm (1 << PIN_LED_bp) 17 | 18 | /* 1sec-interval LED blinking by TCB(Periodic Interrupt Mode) 19 | * Attiny1614's default clock is 20MHz(RC) 20 | * CLK_PER is 3.333MHz ( default prescaler rate is 6, then 20/6 == 3.3 ) 21 | * 22 | * interrupt interval = 1ms ( 3333 / 3.333MHz = 0.001sec ) 23 | * 500ms ON -> 500ms OFF 24 | * 25 | * If you want to write more smart code, 26 | * please use TCA which has an internal prescaler. 27 | */ 28 | #define COMPARE 3333 29 | #define LOOP 500 30 | 31 | int main(void) 32 | { 33 | // LED 34 | PORTA.DIRSET = PIN_LED_bm; 35 | 36 | // TCB0 37 | TCB0.CCMP = COMPARE; 38 | TCB0.INTCTRL = TCB_CAPT_bm; 39 | TCB0.CTRLA = TCB_ENABLE_bm; 40 | 41 | sei(); 42 | 43 | while (1) 44 | { 45 | } 46 | } 47 | 48 | volatile uint16_t count = 0; 49 | ISR(TCB0_INT_vect) 50 | { 51 | count++; 52 | if(count == LOOP){ 53 | count = 0; 54 | if(PORTA.OUT & PIN_LED_bm){ 55 | PORTA.OUTCLR = PIN_LED_bm; 56 | }else{ 57 | PORTA.OUTSET = PIN_LED_bm; 58 | } 59 | } 60 | TCB0.INTFLAGS |= TCB_CAPT_bm; //clear the interrupt flag(to reset TCB0.CNT) 61 | } 62 | -------------------------------------------------------------------------------- /t1614_adc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * t1614_adc.cpp 3 | * 4 | * Created: 2018/11/04 5 | * Author : chromia 6 | */ 7 | 8 | #include 9 | #define F_CPU 3333333 /* 20MHz / 6(default prescale) */ 10 | #include 11 | #include 12 | 13 | /* Pin Assign 14 | * 3.PA5 : LED output (TCB0 WO) 15 | * 4.PB6 : ADC input 16 | */ 17 | #define LED_bp 5 //PB5 18 | #define LED_bm (1< ADC -> TCB(PWM) -> LED(PB5) 26 | 27 | // Port Configuration 28 | PORTA.DIRSET = LED_bm; 29 | PORTA.OUTCLR = LED_bm; 30 | ADC_CTRL &= ~PORT_ISC_gm; 31 | ADC_CTRL |= PORT_ISC_INPUT_DISABLE_gc; // Disable Digital Input Buffer 32 | 33 | // VRef Configuration 34 | VREF.CTRLA = VREF_ADC0REFSEL_4V34_gc; // VRef == 4.34V 35 | 36 | // ADC Configuration 37 | ADC0.CTRLB = ADC_SAMPNUM_ACC1_gc; // No accumulation 38 | ADC0.CTRLC = ADC_REFSEL_INTREF_gc | ADC_PRESC_DIV16_gc; // Internal VRef, CLK_ADC=CLK_PER/16 39 | ADC0.MUXPOS = AIN6; // select target pin 40 | ADC0.CTRLA = ADC_RESSEL_8BIT_gc | ADC_ENABLE_bm; // 8-bit mode 41 | 42 | // TCB Configuration 43 | TCB0.CTRLB = TCB_CNTMODE_PWM8_gc | TCB_CCMPEN_bm; // 8-bit PWM mode, Enable Output to I/O pin 44 | TCB0.CTRLA = !TCB_ENABLE_bm; // not start yet 45 | 46 | volatile uint8_t adcval = 0; 47 | while (1) 48 | { 49 | if(ADC0.INTFLAGS & ADC_RESRDY_bm){ 50 | // Retrieve converted ADC value 51 | adcval = ADC0.RES; 52 | // Update PWM duty rate 53 | TCB0.CTRLA &= ~TCB_ENABLE_bm; 54 | TCB0.CCMP = (adcval << 8) | 0xFF; 55 | TCB0.CNT = 0; 56 | TCB0.CTRLA |= TCB_ENABLE_bm; 57 | } 58 | _delay_ms(100); 59 | // Start A/D Conversion 60 | ADC0.COMMAND |= ADC_STCONV_bm; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /t1614_usart.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * t1614_usart.cpp 3 | * 4 | * Created: 2018/10/26 5 | * Author : chromia 6 | */ 7 | 8 | #include 9 | #define F_CPU 3333333 10 | #include 11 | #include 12 | 13 | /* Pin Assign 14 | * 6. PB3(RxD) : target TxD 15 | * 7. PB2(TxD) : target RxD 16 | */ 17 | 18 | #define PIN_TX_bp 2 // TX = PB2 19 | #define PIN_TX_bm (1 << PIN_TX_bp) 20 | #define PIN_RX_bp 3 // RX = PB3 21 | #define PIN_RX_bm (1 << PIN_RX_bp) 22 | 23 | /* Baud Rate Calculation 24 | * Attiny1614's default clock is 20MHz(RC) 25 | * CLK_PER is 3.333MHz ( default prescaler rate is 6, then 20/6 == 3.3 ) 26 | * 27 | * Requested Baud Rate: f_baud = 9600[bps] 28 | * register parameter: BAUD = floor((64 * CLK_PER ) / (N * f_baud)) 29 | * N = 16 (asynchronous mode) 30 | * -> BAUD = 1389 31 | */ 32 | #define PARAM_BAUD 1389 33 | 34 | volatile uint8_t code = 'x'; 35 | 36 | int main(void) 37 | { 38 | // USART Configuration 39 | PORTB.DIRSET = PIN_TX_bm; // TX as OUTPUT, RX as INPUT 40 | PORTB.OUTSET = PIN_TX_bm; // TX is high 41 | USART0.BAUD = PARAM_BAUD; // Set Baud Rate 42 | USART0.CTRLC = 43 | USART_CMODE_ASYNCHRONOUS_gc | // Mode: Asynchronous[default] 44 | USART_PMODE_DISABLED_gc | // Parity: None[default] 45 | USART_SBMODE_1BIT_gc | // StopBit: 1bit[default] 46 | USART_CHSIZE_8BIT_gc; // CharacterSize: 8bit[default] 47 | USART0.CTRLA = 48 | USART_RXCIE_bm | // Enable RX interrupt 49 | !USART_TXCIE_bm; // Disable TX interrupt 50 | USART0.CTRLB = 51 | USART_RXEN_bm | // Start Receiver 52 | USART_TXEN_bm | // Start Transmitter 53 | USART_RXMODE_NORMAL_gc; // Receiver mode is Normal USART & 1x-speed 54 | 55 | sei(); 56 | 57 | while (1) 58 | { 59 | // Check if TX buffer is empty 60 | if(USART0.STATUS & USART_DREIF_bm){ 61 | USART0.TXDATAL = code; // Transmit a byte 62 | } 63 | _delay_ms(1000); 64 | } 65 | } 66 | 67 | ISR(USART0_RXC_vect) 68 | { 69 | //Receive a byte 70 | code = USART0.RXDATAL; 71 | } 72 | -------------------------------------------------------------------------------- /t1614_spi_master.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * t1614_spi_master.cpp 3 | * 4 | * Created: 2018/11/10 5 | * Author : chromia 6 | */ 7 | 8 | #include 9 | #define F_CPU 3333333 /* 20MHz / 6(default prescale) */ 10 | #include 11 | 12 | /* SPI as Master 13 | * Pin Assign 14 | * 2. PA4 : SS 15 | * 11.PA1 : MOSI 16 | * 12.PA2 : MISO 17 | * 13.PA3 : SCK 18 | * 7. PB2 : LED 19 | */ 20 | #define MOSI_bp 1 21 | #define MOSI_bm (1 << MOSI_bp) 22 | #define MISO_bp 2 23 | #define MISO_bm (1 << MISO_bp) 24 | #define SCK_bp 3 25 | #define SCK_bm (1 << SCK_bp) 26 | #define SS_bp 4 27 | #define SS_bm (1 << SS_bp) 28 | #define LED_bp 2 29 | #define LED_bm (1 << LED_bp) 30 | 31 | #define HIGH 1 32 | #define LOW 0 33 | #define DUMMY 0xFF 34 | 35 | extern void setSS(uint8_t val); 36 | extern uint8_t transfer(uint8_t sendData); 37 | 38 | int main(void) 39 | { 40 | // Port I/O Configuration 41 | PORTA.DIRSET = MOSI_bm | SCK_bm | SS_bm; // Output: MOSI/SCK/SS Input:MISO 42 | PORTB.DIRSET = LED_bm; // Output: LED 43 | 44 | // SPI Configuration 45 | SPI0.CTRLB = 46 | SPI_MODE_2_gc; // Mode2 47 | SPI0.CTRLA = 48 | SPI_MASTER_bm | // as a Master 49 | SPI_PRESC_DIV64_gc | // prescaler = CLK_PER/64 50 | SPI_ENABLE_bm; // Start 51 | 52 | /* 1-sec Interval LED Blinking */ 53 | uint8_t count = 0; 54 | while (1) 55 | { 56 | count = transfer(count); // count up in Slave 57 | if(count >= 100) count = 0; 58 | if(count >= 50){ 59 | PORTB.OUTSET = LED_bm; 60 | }else{ 61 | PORTB.OUTCLR = LED_bm; 62 | } 63 | _delay_ms(10); 64 | } 65 | } 66 | 67 | void setSS(uint8_t val) 68 | { 69 | if(val) PORTA.OUTSET = SS_bm; 70 | else PORTA.OUTCLR = SS_bm; 71 | } 72 | 73 | uint8_t transfer(uint8_t sendData) 74 | { 75 | uint8_t recvData; 76 | 77 | setSS(LOW); 78 | // Send a byte 79 | SPI0.DATA = sendData; 80 | while((SPI0.INTFLAGS & SPI_RXCIE_bm) == 0); 81 | // Receive a byte 82 | SPI0.DATA = DUMMY; 83 | while((SPI0.INTFLAGS & SPI_RXCIE_bm) == 0); 84 | recvData = SPI0.DATA; 85 | setSS(HIGH); 86 | 87 | return recvData; 88 | } 89 | -------------------------------------------------------------------------------- /t1614_rtc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * t1614_rtc.cpp 3 | * 4 | * Created: 2018/11/03 5 | * Author : chromia 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | /* PIN Assign 12 | * 6.TOSC1 : External Xtal 32.768KHz 13 | * 7.TOSC2 : External Xtal 32.768KHz 14 | * 11.PA1 : USART TX 15 | * 12.PA2 : USART RX 16 | */ 17 | 18 | #define PIN_TX_bp 1 // TX = PA1(Alt) 19 | #define PIN_TX_bm (1 << PIN_TX_bp) 20 | #define PIN_RX_bp 2 // RX = PA2(Alt) 21 | #define PIN_RX_bm (1 << PIN_RX_bp) 22 | 23 | /* Baud Rate Calculation 24 | * Attiny1614's default clock is 20MHz(RC) 25 | * CLK_PER is 3.333MHz ( default prescaler rate is 6, then 20/6 == 3.3 ) 26 | * 27 | * Requested Baud Rate: f_baud = 9600[bps] 28 | * register parameter: BAUD = floor((64 * CLK_PER ) / (N * f_baud)) 29 | * N = 16 (asynchronous mode) 30 | * -> BAUD = 1389 31 | */ 32 | #define PARAM_BAUD 1389 33 | 34 | volatile uint8_t code = 'x'; 35 | 36 | #define USE_PIT 0 /* 1:Use PIT Function, 0:Use RTC Function */ 37 | 38 | int main(void) 39 | { 40 | // USART Configuration 41 | PORTMUX.CTRLB |= PORTMUX_USART0_ALTERNATE_gc; // Alternative Pins 42 | PORTA.DIRSET = PIN_TX_bm; // TX as OUTPUT, RX as INPUT 43 | PORTA.OUTSET = PIN_TX_bm; // TX is high 44 | USART0.BAUD = PARAM_BAUD; // Set Baud Rate 45 | USART0.CTRLC = 46 | USART_CMODE_ASYNCHRONOUS_gc | // Mode: Asynchronous[default] 47 | USART_PMODE_DISABLED_gc | // Parity: None[default] 48 | USART_SBMODE_1BIT_gc | // StopBit: 1bit[default] 49 | USART_CHSIZE_8BIT_gc; // CharacterSize: 8bit[default] 50 | USART0.CTRLA = 51 | USART_RXCIE_bm | // Enable RX interrupt 52 | !USART_TXCIE_bm; // Disable TX interrupt 53 | USART0.CTRLB = 54 | USART_RXEN_bm | // Start Receiver 55 | USART_TXEN_bm | // Start Transmitter 56 | USART_RXMODE_NORMAL_gc; // Receiver mode is Normal USART & 1x-speed 57 | 58 | // CLKCTRL Configuration 59 | _PROTECTED_WRITE(CLKCTRL_XOSC32KCTRLA, CLKCTRL_ENABLE_bm); // Enable External Oscillator(32.768kHz Xtal) 60 | 61 | // RTC Configuration 62 | RTC.CLKSEL = RTC_CLKSEL_TOSC32K_gc; // Use 32.768kHz clock as CLK_RTC 63 | #if USE_PIT 64 | // 1[sec]-interval interrupt(PIT version) - simple 65 | RTC.PITINTCTRL = RTC_PI_bm; // Enable PIT Interrupts 66 | RTC.PITCTRLA = RTC_PERIOD_CYC32768_gc | RTC_PITEN_bm; // Run (interval 1[sec]) 67 | #else 68 | // 1[sec]-interval interrupt(RTC version) - more flexible 69 | RTC.INTCTRL = RTC_OVF_bm; 70 | RTC.PER = 0x8000; // Loop every 32768 clocks 71 | RTC.CTRLA = RTC_PRESCALER_DIV1_gc | RTC_RTCEN_bm; // Not Prescaled | Run 72 | #endif 73 | 74 | sei(); 75 | 76 | while (1) 77 | { 78 | } 79 | } 80 | 81 | ISR(USART0_RXC_vect) 82 | { 83 | //Receive a byte 84 | code = USART0.RXDATAL; 85 | } 86 | 87 | void on_tick() 88 | { 89 | // Check if TX buffer is empty 90 | if(USART0.STATUS & USART_DREIF_bm){ 91 | USART0.TXDATAL = code; // Transmit a byte 92 | } 93 | } 94 | 95 | ISR(RTC_CNT_vect) 96 | { 97 | on_tick(); 98 | RTC.INTFLAGS |= RTC_OVF_bm; 99 | } 100 | 101 | ISR(RTC_PIT_vect) 102 | { 103 | on_tick(); 104 | RTC.PITINTFLAGS |= RTC_PI_bm; 105 | } 106 | -------------------------------------------------------------------------------- /t1614_twi.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * t1614_twi.cpp 3 | * I2C Communication Example 4 | * with ACM0802C-NLW-BBW-IIC(8x2 character LCD) 5 | * 6 | * Created: 2018/10/30 7 | * Author : chromia 8 | */ 9 | 10 | #include 11 | #define F_CPU 20000000 12 | #include 13 | #include 14 | #include 15 | 16 | /* Pin Assign 17 | * ATTiny1614 18 | * 8. PB1 -> SDA 19 | * 9. PB0 -> SCL 20 | * 21 | * ACM0802C 22 | * 1. Vss : GND 23 | * 2. Vdd : +5V 24 | * 3. Vo : Potentiometer(10Kohm) 25 | * 4. SA1 : GND 26 | * 5. SA0 : GND 27 | * 6. SDA : 1614_PB1 (&PullUp) 28 | * 7. SCL : 1614_PB0 (&PullUp) 29 | * 8. NC 30 | * 9. BL+ : +5V 31 | * 10.BL- : GND 32 | */ 33 | 34 | 35 | /* TWI Baud Rate Calculation 36 | * CLK_PER is 20MHz 37 | * Target is ACM0802C I2C(8x2 Character LCD Module) 38 | * 39 | * Requested Baud Rate: f_SCL = 400[KHz] 40 | * register parameter: BAUD = (CLK_PER - f_SCL*(10+CLK_PER*t_RISE)) / (2*f_SCL) 41 | * t_RISE = 300[ns] = 3.0e-7[s] 42 | * -> BAUD = 17 43 | */ 44 | #define TWI_PARAM_BAUD 17 45 | 46 | #define TWI_BUFFER_SIZE 3 47 | uint8_t twi_buffer[TWI_BUFFER_SIZE]; 48 | volatile uint8_t *twi_ptr; 49 | volatile uint8_t twi_rest; 50 | volatile bool twi_sending = false; 51 | volatile bool twi_error = false; 52 | 53 | #define LCD_ADDR 0x78 // 01111[0][0][0] <- SA1 SA0 W 54 | #define LCD_ADDR_R 0x79 // 01111[0][0][1] <- SA1 SA0 R 55 | #define LCD_COMMAND 0x00 // [0][0]000000 <- LastByte RS 56 | #define LCD_DATA 0x40 // [0][1]000000 57 | 58 | 59 | bool TWI_init() 60 | { 61 | // TWI Configuration 62 | TWI0.MBAUD = TWI_PARAM_BAUD; 63 | TWI0.MCTRLA = TWI_WIEN_bm | TWI_ENABLE_bm; 64 | TWI0.MSTATUS |= (TWI_RIF_bm | TWI_WIF_bm); 65 | TWI0.MSTATUS |= TWI_BUSSTATE_IDLE_gc; 66 | return true; 67 | } 68 | 69 | bool TWI_sendMessage(uint8_t address, const uint8_t *message, uint8_t length) 70 | { 71 | // Copy Message Data 72 | if(length > TWI_BUFFER_SIZE) return false; 73 | memcpy(twi_buffer, message, length); 74 | twi_ptr = twi_buffer; 75 | twi_rest = length; 76 | 77 | twi_sending = true; 78 | 79 | // Send Slave Address(Start Sending) 80 | TWI0.MADDR = address; 81 | 82 | // Wait until finished 83 | while(twi_sending); 84 | 85 | return !twi_error; 86 | } 87 | 88 | ISR(TWI0_TWIM_vect) 89 | { 90 | if(TWI0.MSTATUS & TWI_RXACK_bm){ 91 | twi_error = true; 92 | twi_sending = false; 93 | } 94 | if(twi_rest){ 95 | // Send Next Character 96 | --twi_rest; 97 | TWI0.MSTATUS |= (TWI_WIF_bm || TWI_RIF_bm); 98 | TWI0.MDATA = *twi_ptr++; 99 | }else{ 100 | // Generate STOP Condition 101 | TWI0.MCTRLB |= TWI_ACKACT_NACK_gc; 102 | TWI0.MCTRLB |= TWI_MCMD_STOP_gc; 103 | twi_sending = false; 104 | } 105 | } 106 | 107 | bool LCD_setMessage(uint8_t address, uint8_t cont, uint8_t data) 108 | { 109 | uint8_t msg[] = { cont, data }; 110 | return TWI_sendMessage(address, msg, 2); 111 | } 112 | 113 | int main(void) 114 | { 115 | // System Clock 116 | _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0); // Disable prescaler ( CLK_PER=20MHz ) 117 | 118 | _delay_ms(40); // Wait until the LCD is ready 119 | 120 | TWI_init(); 121 | 122 | sei(); 123 | 124 | // Send Commands 125 | LCD_setMessage(LCD_ADDR, LCD_COMMAND, 0x01); // Clear Display 126 | _delay_ms(2); 127 | LCD_setMessage(LCD_ADDR, LCD_COMMAND, 0x38); // Function Set : 8bitI/F, 2Line, 5x8Font 128 | _delay_us(50); 129 | LCD_setMessage(LCD_ADDR, LCD_COMMAND, 0x0C); // Display ON/OFF : display=ON, cursor=OFF, blink=OFF 130 | _delay_us(50); 131 | LCD_setMessage(LCD_ADDR, LCD_COMMAND, 0x06); // Entry Mode Set : Step to Right 132 | _delay_us(50); 133 | // Write Data 134 | LCD_setMessage(LCD_ADDR, LCD_DATA, 0x48); // Write Data : 'H' 135 | _delay_ms(2); 136 | LCD_setMessage(LCD_ADDR, LCD_DATA, 0x45); // Write Data : 'E' 137 | _delay_ms(2); 138 | LCD_setMessage(LCD_ADDR, LCD_DATA, 0x4C); // Write Data : 'L' 139 | _delay_ms(2); 140 | LCD_setMessage(LCD_ADDR, LCD_DATA, 0x4C); // Write Data : 'L' 141 | _delay_ms(2); 142 | LCD_setMessage(LCD_ADDR, LCD_DATA, 0x4F); // Write Data : 'O' 143 | _delay_ms(2); 144 | 145 | while(1) 146 | { 147 | 148 | } 149 | } 150 | --------------------------------------------------------------------------------