ARM11 GPIO口模拟I2C驱动AT24C08

简单的测试通信时序

 

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/cdev.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/ctype.h>
#include <linux/pagemap.h>
#include <linux/delay.h>
#include <linux/miscdevice.h>

#include <mach/regs-gpio.h>
#include <mach/gpio.h>
#include <mach/hardware.h>
#include <mach/map.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/signal.h>
#include <asm/uaccess.h>
#include <plat/regs-timer.h>
#include <plat/gpio-cfg.h>
#include <mach/gpio-bank-b.h>

#define write_cmd 0xa0
#define read_cmd 0xa1

#define SDA_output  s3c_gpio_cfgpin(S3C64XX_GPB(6),S3C_GPIO_OUTPUT)
#define SDA_input   s3c_gpio_cfgpin(S3C64XX_GPB(6),S3C_GPIO_INPUT)

//#define SDA_output  s3c_gpio_cfgpin(S3C64XX_GPB(6),S3C64XX_GPB_OUTPUT(6))
//#define SDA_input   s3c_gpio_cfgpin(S3C64XX_GPB(6),S3C64XX_GPB_INPUT(6)) 

#define SCLK_output s3c_gpio_cfgpin(S3C64XX_GPB(5),S3C64XX_GPB_OUTPUT(5))

#define DEVICE_NAME "yzh_eeprom"


void SDA_set(unsigned int value)
{
 int temp;
 
 temp = __raw_readl(S3C64XX_GPBDAT);
 temp &= ~(1<<6);
 temp |= (value << 6);
 __raw_writel(temp,S3C64XX_GPBDAT);
}

unsigned int Get_SDA(void)
{
 int tmp;
 
 tmp = __raw_readl(S3C64XX_GPBDAT);
 tmp = tmp & (1 << 6);

 return tmp;
}

void SCLK_set(unsigned int value)
{
 int tp;

 tp = __raw_readl(S3C64XX_GPBDAT);
 tp &= ~(1<<5);
 tp |= (value << 5);
 __raw_writel(tp,S3C64XX_GPBDAT);
}

void AT_eeprom_start(void)
{
 SDA_output;
 SCLK_output;
 
 SDA_set(1);
 SCLK_set(1);
 mdelay(1);

 SDA_set(0);
 mdelay(2);
 SCLK_set(0);
 udelay(10);

void AT_eeprom_stop(void)
{
 SDA_output;
 SCLK_output;
 
 SCLK_set(1);
 SDA_set(0);
 mdelay(1);

 SDA_set(1);
 mdelay(2);
 SCLK_set(0);
 udelay(10);
}

void master_noack(void)
{
 SDA_output;
 SCLK_output;
 
 SDA_set(1);
 mdelay(3);
 SCLK_set(0);
 mdelay(2);
 SCLK_set(1);
 SCLK_set(0);
 mdelay(2);
}

unsigned int master_get_ack(void)
{
 int ack; 
  
 SDA_output;
 SCLK_output;

 SDA_set(1);
 SCLK_set(0);
 mdelay(3);

 SDA_input; 
 SCLK_set(1);
 mdelay(5);
 ack = Get_SDA();

 SCLK_set(0);

 return ack;
}

void AT_eeprom_byte_program(unsigned int dat)
{
 int i;
 SDA_output;
 SCLK_output;

 SDA_set(1);

 for(i=0; i<8; i++)
 {
  if(dat & 0x80)
  {
   SDA_set(1);
  }
  else
  {
   SDA_set(0);
  }
 // udelay(100);
  SCLK_set(1);
  udelay(100);
  SCLK_set(0);
  dat <<= 1;
 }

unsigned int AT_eeprom_byte_read(void)
{
 int j;
 unsigned int result = 0;
 SCLK_output; 
 SDA_input;

 SCLK_set(0);
 udelay(10);

 for(j=0; j<8; j++)
 {     
  result <<= 1;
  SCLK_set(0);
  udelay(10);
  SCLK_set(1);  
  udelay(10);
  
  
//  result |= Get_SDA();
  if(Get_SDA() == 0)
  {
   result &= ~0x01;
  }
  else
  {
   result |= 0x01;
  }
  
  
      
 } 
 return result;
}

void AT_eeprom_write(unsigned int addr,unsigned int dat)
{
 int ack_flag =1;

 AT_eeprom_start();
 udelay(200);
 AT_eeprom_byte_program(write_cmd);
 udelay(200);
 ack_flag = master_get_ack();
 printk("write_1: %x \n",ack_flag);
 if(ack_flag == 0)
 {
  AT_eeprom_byte_program(addr);
  ack_flag = master_get_ack();
  printk("write_2: %x \n",ack_flag);
  if(ack_flag == 0)
  { 
   AT_eeprom_byte_program(dat);
   ack_flag = master_get_ack();
   printk("write_3: %x \n",ack_flag);
   if(ack_flag == 0)
   {
    AT_eeprom_stop();
    udelay(200);
   }
  }
 }
}

unsigned int AT_eeprom_read(unsigned int address)
{
 int ack_read = 1;
 unsigned int read_value = 0;
 
 AT_eeprom_start();
 udelay(200);
 AT_eeprom_byte_program(write_cmd);
 udelay(200);
 ack_read = master_get_ack();
 printk("read_1: %x \n",ack_read);
 if(ack_read == 0)
 {
  AT_eeprom_byte_program(address); 
  ack_read = master_get_ack();
  printk("read_2: %x \n",ack_read);
  if(ack_read == 0)
  {
   AT_eeprom_start();
   udelay(100);
   AT_eeprom_byte_program(read_cmd);
   ack_read = master_get_ack();
   printk("read_3: %x \n",ack_read);
   if(ack_read == 0)
   {
    read_value = AT_eeprom_byte_read();
    master_noack();
    AT_eeprom_stop();
    udelay(100); 
   }
  }
 }
 return read_value;
}

void eeprom_test(void)
{
 unsigned int last_value = 0;
 
 AT_eeprom_write(0x01,0x11);
 last_value = AT_eeprom_read(0x01);
 printk("eeprom_value1: %x \n\r",last_value);

 AT_eeprom_write(0x01,0x22);
 last_value = AT_eeprom_read(0x01);
 printk("eeprom_value2: %x \n\r",last_value);

 AT_eeprom_write(0x01,0x33);
 last_value = AT_eeprom_read(0x01);
 printk("eeprom_value3: %x \n\r",last_value);
}

static int eeprom_open(struct inode *inode, struct file *filp)
{
 printk("the eeprom module has opened \n\r");
 eeprom_test();
 return 0;
}

static int eeprom_release(struct inode *inode, struct file *filp)
{
 printk("the eeprom module has release \n\r");

 return 0;
}

static struct file_operations eeprom_fops = {
 .open = eeprom_open,
 .release = eeprom_release,
};

static struct miscdevice eeprom_misc = {
 .minor = MISC_DYNAMIC_MINOR,
 .name = DEVICE_NAME,
 .fops = &eeprom_fops,
};

static int eeprom_init(void)
{
 int ret;
 ret = misc_register(&eeprom_misc);
 printk("the eeprom module has up \n\r");
 return ret;
}

static void eeprom_exit(void)
{
 misc_deregister(&eeprom_misc);
 printk("the eeprom module has exit \n\r");
}

module_init(eeprom_init);
module_exit(eeprom_exit);

MODULE_LICENSE("GPL"); 

转载于:https://my.oschina.net/rabbityzh/blog/167834

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于STM32的AT24C512 I2C驱动的示例代码,使用了HAL库: ``` #include "stm32f1xx_hal.h" #define EEPROM_ADDRESS 0xA0 // AT24C512的I2C地址 I2C_HandleTypeDef hi2c1; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_I2C1_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_I2C1_Init(); uint8_t tx_data[2]; // 存储要写入的数据 uint8_t rx_data; // 存储要读取的数据 tx_data[0] = 0x00; // 要写入的EEPROM地址 tx_data[1] = 0x55; // 要写入的数据 HAL_I2C_Master_Transmit(&hi2c1, EEPROM_ADDRESS, tx_data, 2, 1000); // 写入数据 HAL_Delay(10); // 等待EEPROM写入完成 tx_data[0] = 0x00; // 要读取的EEPROM地址 HAL_I2C_Master_Transmit(&hi2c1, EEPROM_ADDRESS, tx_data, 1, 1000); // 发送要读取的地址 HAL_I2C_Master_Receive(&hi2c1, EEPROM_ADDRESS, &rx_data, 1, 1000); // 读取数据 while (1) { } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } static void MX_I2C1_Init(void) { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { __HAL_RCC_GPIOC_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); } void Error_Handler(void) { while (1) { } } ``` 在这个示例中,我们首先设置了系统时钟、GPIOI2C。然后在主函数中,我们定义了要写入的数据和要读取的数据的变量,写入数据的过程是先设置要写入的EEPROM地址和要写入的数据,然后使用HAL_I2C_Master_Transmit函数向AT24C512芯片写入数据。读取数据的过程是先设置要读取的EEPROM地址,然后使用HAL_I2C_Master_Transmit函数向AT24C512芯片发送要读取的地址,最后使用HAL_I2C_Master_Receive函数从芯片中读取数据。注意,在写入数据后需要加一个延迟,以等待EEPROM写入完成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值