21,597
社区成员
发帖
与我相关
我的任务
分享
/**
* \file
* A very simple Contiki application about i2c
*/
#include "contiki.h"
#include "shell.h"
#include <stdio.h> /* For printf() */
#include <string.h>
#include "sys/clock.h"
#include "dev/i2c.h"
#include "dev/serial-line.h"
#include "dev/sys-ctrl.h"
#include "dev/gpio.h"
#include "dev/ioc.h"
/*---------------------------------------------------------------------------*/
PROCESS(shell_i2c_process, "i2c");
SHELL_COMMAND(i2c_command,
"i2c",
"i2c: will start i2c test",
&shell_i2c_process);
/*---------------------------------------------------------------------------*/
#define END '\n'
#define BUFSIZE 128
#define SLAVE_ADDRESS 0x3C
#if (BUFSIZE & (BUFSIZE - 1) != 0)
#error UART_BUFSIZE must be a power of two
#error Chang UART_BUFSIZE
#endif
int my_i2c_input(unsigned char c);
void i2c_loop_init(void);
void i2c_init(void);
void echo_m_stat(void);
void echo_s_stat(void);
char *txbuf;
void master_slave_loopback_test(void *);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_i2c_process, ev, data)
{
PROCESS_BEGIN();
printf("Enter a string for I2C test \n");
while (1) {
PROCESS_WAIT_EVENT_UNTIL(ev == serial_line_event_message && data != NULL);
master_slave_loopback_test(data);
printf("end of transmission\n");
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
void
shell_i2c_init(void)
{
shell_register_command(&i2c_command);
}
/*---------------------------------------------------------------------------*/
void
i2c_loop_init(void)
{
/* Enable clock for the I2C while Running */
REG(SYS_CTRL_RCGCI2C) = 1;
/* RESET of I2C module */
REG(SYS_CTRL_SRI2C) = 1;
GPIO_SET_INPUT(GPIO_PORT_TO_BASE(CC2538_I2C_SCL_PORT_NUM), GPIO_PIN_MASK(CC2538_I2C_SCL_PIN_NUM));
GPIO_SET_INPUT(GPIO_PORT_TO_BASE(CC2538_I2C_SDA_PORT_NUM), GPIO_PIN_MASK(CC2538_I2C_SDA_PIN_NUM));
/* Put all the I2C gpios into peripheral mode */
GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(CC2538_I2C_SCL_PORT_NUM), GPIO_PIN_MASK(CC2538_I2C_SCL_PIN_NUM));
GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(CC2538_I2C_SDA_PORT_NUM), GPIO_PIN_MASK(CC2538_I2C_SDA_PIN_NUM));
/* Disable any pull ups or the like */
ioc_set_over(CC2538_I2C_SCL_PORT_NUM, CC2538_I2C_SCL_PIN_NUM, IOC_OVERRIDE_DIS);
ioc_set_over(CC2538_I2C_SDA_PORT_NUM, CC2538_I2C_SDA_PIN_NUM, IOC_OVERRIDE_DIS);
/* Set the mux correctly to connect the I2C pins to the correct GPIO pins */
/* input */
REG(IOC_I2CMSSCL) = (CC2538_I2C_SCL_PORT_NUM << 3) + CC2538_I2C_SCL_PIN_NUM;
REG(IOC_I2CMSSDA) = (CC2538_I2C_SDA_PORT_NUM << 3) + CC2538_I2C_SDA_PIN_NUM;
/* output */
ioc_set_sel(CC2538_I2C_SCL_PORT_NUM, CC2538_I2C_SCL_PIN_NUM, IOC_PXX_SEL_I2C_CMSSCL);
ioc_set_sel(CC2538_I2C_SDA_PORT_NUM, CC2538_I2C_SDA_PIN_NUM, IOC_PXX_SEL_I2C_CMSSDA);
/* enable LOOP */
REG(I2CM_CR) |= I2CM_CR_LPBK;
/* enable master mode */
REG(I2CM_CR) |= I2CM_CR_MFE;
/* Configure the SCL 100Kbps */
REG(I2CM_TPR) = 7;
/* enable slave mode*/
REG(I2CM_CR) |= I2CM_CR_SFE;
REG(I2CS_CTRL) = I2CS_CTRL_DA;
/* set slave own address */
REG(I2CS_OAR) = SLAVE_ADDRESS;
/* Tell the master module what address it will place on the bus */
REG(I2CM_SA) = (SLAVE_ADDRESS << 1) | 0;
}
/*---------------------------------------------------------------------------*/
void
master_slave_loopback_test(void *data)
{
static int i, j;
static char *txbuf;
static char rxbuf[128] = "";
txbuf = (char *)data;
i2c_loop_init();
printf("\n\n\nI2C Loopback Example ->\n");
printf(" Module = I2C\r\n");
printf(" Mode = Single Send/Receive\n");
printf(" Rate = 100kbps\n");
printf("\nTranferring from: Master -> Slave\n");
for (i = 0; i < strlen(txbuf); i++) {
printf(" Sending: %c . . .", txbuf[i]);
flush();
/*send 1 byte*/
REG(I2CM_DR) = txbuf[i];
/* 发送命令让数据发出 */
REG(I2CM_CTRL) = I2C_MASTER_CMD_SINGLE_SEND;
/* 如果收到数据,从机拉低数据线拖延主机,如果没有收到,则等待 */
while(!REG(I2CS_STAT) & I2C_SLAVE_ACT_RREQ)
echo_s_stat();
rxbuf[i] = REG(I2CS_DR);
printf("%c\n", rxbuf[i]);
}
printf("receive string: %s\n", rxbuf);
}
/*-------------------------------------------------------- */
void
echo_m_stat(void)
{
static int stat;
printf("master stat: \n");
stat = REG(I2CM_STAT);
if (stat & I2CM_STAT_BUSY) {
printf("i2c_busy\n");
return;
}
if (stat & I2CM_STAT_ERROR)
printf("has error\n");
if (stat & I2CM_STAT_BUSBSY)
printf("i2c_bus_busy\n");
if (stat & I2CM_STAT_IDLE)
printf("i2c_idle\n");
if (stat & I2CM_STAT_ARBLST)
printf("lost arblst\n");
if (stat & I2CM_STAT_DATACK)
printf("send data not rev ack\n");
if (stat & I2CM_STAT_ADRACK)
printf("send address not rev ack\n");
}
/* ------------------------------------------------------- */
void
echo_s_stat(void)
{
static int stat;
printf("slave stat: \n");
stat = REG(I2CS_STAT);
if (stat & I2C_SLAVE_ACT_RREQ) {
printf("master has sent data\n");
if (stat & I2C_SLAVE_ACT_RREQ_FBR)
printf("master has sent first byte\n");
}
if (stat & I2C_SLAVE_ACT_TREQ)
printf("mast has requested data\n");
}
/* RESET of I2C module */
REG(SYS_CTRL_SRI2C) = 1;