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

📄 avr-i2c.c

📁 MANTIS是由科罗拉多大学开发的传感器网络嵌入式操作系统。 这是mantis的0.9.5版本的源码。
💻 C
字号:
//  This file is part of MANTIS OS, Operating System//  See http://mantis.cs.colorado.edu/////  Copyright (C) 2003,2004,2005 University of Colorado, Boulder////  This program is free software; you can redistribute it and/or//  modify it under the terms of the mos license (see file LICENSE)#include "mos.h"#ifdef ARCH_AVR#include "sem.h"#include "dev.h"#include "led.h"#include "mutex.h"#include "avr-i2c.h"#include "printf.h"mos_mutex_t i2c_mutex;static mos_sem_t i2c_sem_read;static mos_sem_t i2c_sem_write;static boolean reading;static uint8_t *read_buf;static uint16_t read_count;static uint16_t read_max;static uint8_t *write_buf;static uint16_t write_count;static uint16_t write_max;static uint8_t mode;static uint8_t state;static uint8_t SLA_W;#define avr_i2c_wait_status_read(status_code)	\   while(!(TWCR & (1<<TWINT)))                  \   ;                                            \                                                \   if(avr_i2c_get_status() != status_code)      \   {					        \      mos_mutex_unlock (&i2c_mutex);	        \      return read_count;		        \   }					        \#define avr_i2c_wait_status_write(status_code)	 \   while(!(TWCR & (1<<TWINT)))                   \   ;                                             \                                                 \   if(avr_i2c_get_status() != status_code)       \   {					         \      mos_mutex_unlock (&i2c_mutex);	         \      return write_count;		         \   }					         \uint16_t dev_read_DEV_AVR_I2C(void *buf, uint16_t count){   if(count == 0)      return 0;      if(mode == DEV_MODE_OFF)      avr_i2c_enable();      read_max = count;   read_count = 0;   read_buf = (uint8_t *)buf;   reading = true;   uint8_t polling = true;   if(polling)   {      //transmit a start condition      TWCR |= (1 << TWINT) | (1<<TWSTA);      //wait for response      avr_i2c_wait_status_read(START);      //transmit SLA+R      avr_i2c_put_byte(SLA_W | 0x01); //lsb = 1 for read      //wait for response      TWCR = (1 << TWINT) | (1 << TWEN);      avr_i2c_wait_status_read(MR_SLA_ACK);      //get count -1 bytes and return ACK      while(read_count < read_max - 1){	 TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);	 //wait for response	 avr_i2c_wait_status_read(MR_DATA_ACK);	 read_buf[read_count++] = avr_i2c_get_byte();      }      //get last byte, return NACK      TWCR = (1 << TWINT) | (1 << TWEN);            //wait for response      avr_i2c_wait_status_read(MR_DATA_NACK);      read_buf[read_count++] = avr_i2c_get_byte();      //issue a stop condition      TWCR = (1 << TWSTO) | (1 << TWINT);         } else {      mos_sem_wait (&i2c_sem_read);   }   if(mode == DEV_MODE_OFF)      avr_i2c_disable();      mos_mutex_unlock(&i2c_mutex);   return read_count;}uint16_t dev_write_DEV_AVR_I2C (const void *buf, uint16_t count){   uint8_t int_handle;   mos_mutex_lock (&i2c_mutex);   //initialize counting vars   write_count = 0;   write_max = count;   write_buf = (uint8_t *)buf;      if(mode == DEV_MODE_OFF)      avr_i2c_enable();   state = START;   reading = false;   uint8_t polling = true;   if(polling) {      TWCR |= (1 << TWINT) | (1<<TWSTA);      avr_i2c_wait_status_write(START);      avr_i2c_put_byte(SLA_W);      TWCR = (1 << TWINT) | (1 << TWEN);      avr_i2c_wait_status_write(MT_SLA_ACK);      while(write_count < write_max) {	 TWDR = write_buf[write_count++];	 TWCR = (1 << TWINT) | (1 << TWEN);	 avr_i2c_wait_status_write(MT_DATA_ACK);      }      TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);   } else {      int_handle = mos_disable_ints();      avr_i2c_interrupt_enable(); //enable interrupt mode      avr_i2c_clear_int_flag(); //clear old flag      avr_i2c_start_condition(); //initiate start condition            mos_led_display(5);      mos_enable_ints(int_handle);      mos_led_display(4);      mos_sem_wait(&i2c_sem_write);   }      if(mode == DEV_MODE_OFF)      avr_i2c_disable();      mos_mutex_unlock(&i2c_mutex);   return write_count;}uint8_t dev_mode_DEV_AVR_I2C (uint8_t newMode){   mode = newMode;   switch (newMode) {   case DEV_MODE_ON:      avr_i2c_enable();      break;   case DEV_MODE_OFF:      avr_i2c_disable();      break;   default:      return DEV_UNSUPPORTED;   }   return DEV_OK;}uint8_t dev_ioctl_DEV_AVR_I2C (int8_t request, ...){   uint8_t input;   va_list ap;   va_start(ap, request);   switch (request) {   case I2C_ENABLE_ACK:      TWCR |= (1 << TWEA);      break;   case I2C_DISABLE_ACK:      TWCR &= ~(1 << TWEA);      break;   case I2C_DEST_ADDR:      input = (uint8_t)va_arg (ap, uint16_t);      SLA_W = (input << 1);      break;   case I2C_SLAVE_ADDR:      TWAR |= va_arg (ap, uint16_t);      break;   case I2C_SET_BRR:      input = (uint8_t)va_arg (ap, uint16_t);      TWBR = input;      break;   default:      return DEV_BAD_IOCTL;   }   return DEV_OK;}void avr_i2c_init(void){   mode = DEV_MODE_OFF;   mos_mutex_init(&i2c_mutex);   mos_sem_init(&i2c_sem_write, 0);   mos_sem_init(&i2c_sem_read, 0);   avr_i2c_disable();}SIGNAL (SIG_TWI) {   mos_led_display(3);   if(reading){      switch (state) {      case START:	 if(avr_i2c_get_status() != START) {	    mos_sem_post (&i2c_sem_read);	    return;	 }	 	 avr_i2c_put_byte (TWAR >> 1); //write SLA+R for master - receiver	 state = MR_SLA_ACK;	 //Clear TWINT bit in TWCR to start xmission of address	 avr_i2c_clear_int_flag (); 	 break;      case MR_SLA_ACK:	 if(avr_i2c_get_status() != MR_SLA_ACK) {	    mos_sem_post (&i2c_sem_read);	    	    return;	 }	 	 read_buf[read_count++] = avr_i2c_get_byte();	 state = MR_DATA_ACK; 	 avr_i2c_clear_int_flag (); 	 break;      case MR_DATA_ACK:	 if(avr_i2c_get_status() != MR_DATA_ACK){	    mos_sem_post (&i2c_sem_read);	    return;	 }	    	 if(read_count < read_max){ //still reading	    read_buf[read_count++] = avr_i2c_get_byte();	    avr_i2c_clear_int_flag ();	 } else { //done reading	    //send a NACK after last recieved byte	    avr_i2c_stop_condition ();	    avr_i2c_interrupt_disable ();	    mos_sem_post (&i2c_sem_read);	 }	 break;      default:	 return;      }   } else { //writing      switch (state) {      case START:	 if(avr_i2c_get_status() != START) {	    mos_sem_post (&i2c_sem_write);	    return;	 }         avr_i2c_put_byte(SLA_W); //Load SLA_W into TWDR Register	 	 state = MT_SLA_ACK;	 //Clear TWINT bit in TWCR to start xmission of address	 avr_i2c_clear_int_flag (); 	 break;      case MT_SLA_ACK:	 if(avr_i2c_get_status() != MT_SLA_ACK) {	    mos_sem_post (&i2c_sem_write);	    return;	 }	 	 avr_i2c_put_byte(write_buf[write_count++]); //write one byte	 	 state = MT_DATA_ACK;	 	 avr_i2c_clear_int_flag (); //clear int to start xmission	 break;      case MT_DATA_ACK:	 if(avr_i2c_get_status() != MT_DATA_ACK) {	    mos_sem_post (&i2c_sem_write);	    return;	 }	 	 if(write_count < write_max){	    avr_i2c_put_byte(write_buf[write_count++]); //write one byte	    avr_i2c_clear_int_flag (); //clear int to start xmission	 } else {	    avr_i2c_stop_condition ();	    avr_i2c_clear_int_flag ();	    state = MT_DATA_DONE;	 }	 break;      case MT_DATA_DONE:	 avr_i2c_interrupt_disable ();	 mos_sem_post(&i2c_sem_write);	 break;      default:	 return;      } // switch   } //if reading  }#endif

⌨️ 快捷键说明

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