stm8l I2C 双机通信 互为主从(写的不好,能工作)官方版整合

2019-12-26 18:55发布

本帖最后由 lovepig200 于 2014-2-10 16:23 编辑

两个stm8l 互为主从,默认从机模式,按键后切换为主机模式发送。两个mcu可以互为主从。


main.c

#include "stm8l15x.h"
//#include "stm8_eval.h"
#include "main.h"


/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define KEYESC_PORT GPIOD        // 退出出键
#define KEYESC_PIN GPIO_Pin_4
#define KEYNEX_PORT GPIOD        //下一个键
#define KEYNEX_PIN GPIO_Pin_5

#define KEYESC_DOWN  GPIO_ReadInputDataBit(KEYESC_PORT, KEYESC_PIN) == RESET
#define KEYNEX_DOWN  GPIO_ReadInputDataBit(KEYNEX_PORT, KEYNEX_PIN) == RESET

#define LED_PORT GPIOB
#define LED_REDPIN GPIO_Pin_3
#define LED_GREPIN GPIO_Pin_4

/* Private macro -------------------------------------------------------------*/
extern uint8_t HEADER_ADDRESS_Read = (((SLAVE_ADDRESS & 0xFF00) >> 7) | 0xF1);
extern uint8_t HEADER_ADDRESS_Write;
/* Private variables ---------------------------------------------------------*/
__IO uint8_t Rx_Idx = 0, Tx_Idx = 0;
__IO uint8_t SL_Rx_Idx = 0, SL_Tx_Idx = 0;
__IO uint8_t NumByteToRead = BUFFERSIZE;
__IO uint8_t NumOfBytes = BUFFERSIZE;

unsigned char IIC_STA = 0;

uint8_t i = 0;
uint8_t p = 0;
__IO uint8_t RxBuffer[BUFFERSIZE];
TestStatus TransferStatus1 = FAILED;
extern __IO uint8_t TxBuffer[BUFFERSIZE];
/* Private function prototypes -----------------------------------------------*/
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);
void Delay(__IO uint32_t nCount);
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */

static void GPIO_Config(void)
{

  
//GPIO_Init(PINA_PORT,PINA_PIN,GPIO_Mode_In_PU_No_IT);
//GPIO_Init(PINB_PORT,PINB_PIN,GPIO_Mode_In_PU_No_IT);
//GPIO_Init(OKKEY_PORT,OKKEY_PIN,GPIO_Mode_In_PU_No_IT);
GPIO_Init(LED_PORT,LED_REDPIN | LED_GREPIN,GPIO_Mode_Out_PP_Low_Slow);
//GPIO_Init(MOTER_PORT,PUL_PIN | EN_PIN | DIR_PIN,GPIO_Mode_Out_PP_Low_Slow);
//GPIO_Init(AIRP_PORT,AIRP_PIN,GPIO_Mode_In_PU_No_IT);
GPIO_Init(KEYNEX_PORT,KEYNEX_PIN,GPIO_Mode_In_PU_No_IT);
GPIO_Init(KEYESC_PORT,KEYESC_PIN,GPIO_Mode_In_PU_No_IT);
}

void I2C_SETUP(unsigned char Addr)
{
   /* I2C  clock Enable*/
  CLK_PeripheralClockConfig(CLK_Peripheral_I2C1, ENABLE);  
  /* Initialize I2C peripheral */
  I2C_Init(I2C1, 100000, Addr,
           I2C_Mode_I2C, I2C_DutyCycle_2,
           I2C_Ack_Enable, I2C_AcknowledgedAddress_7bit);
}
unsigned char I2C_MASTER_SEND(void) //应用此函数前 需要准备好要发送的数据,存在TxBuffer[]中,并设置好发送接收数据数量
{
unsigned char timeout = 0;
  /* Enable Buffer and Event Interrupt*/
  I2C_ITConfig(I2C1, (I2C_IT_TypeDef)(I2C_IT_EVT | I2C_IT_BUF) , ENABLE);
  I2C_AcknowledgeConfig(I2C1, ENABLE);
    /* Send START condition */
  I2C_GenerateSTART(I2C1, ENABLE);
  while (NumOfBytes)
  {
    Delay(0x000F);
    timeout++;
    if(timeout > 10)
    {
      return 2;
    }
  }
  while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
  return 1;
}

void I2C_MASTER_RECEIVE(__IO uint8_t *RxBuffer,unsigned char ByteToRead)
{
  unsigned char Rx_Idx = 0;
   /*****  reception phase ***/
  /*  Wait while the bus is busy */
  while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

  /* Send START condition */
  I2C_GenerateSTART(I2C1, ENABLE);

  /* Test on EV5 and clear it */
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

  /* Send slave Address for write */
  I2C_Send7bitAddress(I2C1, SLAVE_ADDRESS, I2C_Direction_Receiver);

  /* Test on EV6 and clear it */
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));


  /* While there is data to be read */
  while (ByteToRead)
  {
    if (ByteToRead == 1)
    {
      /* Disable Acknowledgement */
      I2C_AcknowledgeConfig(I2C1, DISABLE);

      /* Send STOP Condition */
      I2C_GenerateSTOP(I2C1, ENABLE);

      /* Poll on RxNE Flag */
      while ((I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET));
      /* Read a byte from the Slave */
      RxBuffer[Rx_Idx] = I2C_ReceiveData(I2C1);

      /* Point to the next location where the byte read will be saved */
      Rx_Idx++;

      /* Decrement the read bytes counter */
      ByteToRead--;
    }

    /* Test on EV7 and clear it */
    if (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) )
    {
      /* Read a byte */
      RxBuffer[Rx_Idx] = I2C_ReceiveData(I2C1);

      /* Point to the next location where the byte read will be saved */
      Rx_Idx++;

      /* Decrement the read bytes counter */
      ByteToRead--;
    }

  }
}

void main()
{

  CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_2);
  GPIO_Config();
  I2C_SETUP(SLAVE_ADDRESS);
  I2C_ITConfig(I2C1, (I2C_IT_TypeDef)(I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF), ENABLE);
  enableInterrupts();
while(1)
  {
if(KEYESC_DOWN)
{
  IIC_STA = 1;
  I2C_SETUP(MASTER_ADDRESS);
  GPIO_SetBits(LED_PORT,  LED_REDPIN );
  NumByteToRead = BUFFERSIZE;
  NumOfBytes = BUFFERSIZE;
  Tx_Idx = 0;
  /* TXBuffer initialization */
  for (i = 0; i < BUFFERSIZE; i++)
  {
    TxBuffer = i;
  }
  p = I2C_MASTER_SEND();

  /* Add a delay to be sure that communication is finished */
  Delay(0x0FFF);
  
I2C_MASTER_RECEIVE(RxBuffer,NumByteToRead);
Delay(0xfFFF);
Delay(0xfFFF);
GPIO_ResetBits(LED_PORT,  LED_REDPIN );
I2C_SETUP(SLAVE_ADDRESS);
I2C_ITConfig(I2C1, (I2C_IT_TypeDef)(I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF), ENABLE);
IIC_STA = 0;
}
  }
}



/**
  * @brief  Inserts a delay time.
  * @param  nCount: specifies the delay time length.
  * @retval None
  */
void Delay(__IO uint32_t nCount)
{
  for (; nCount != 0; nCount--);
}





stm8l15x_it.c

#include "stm8l15x_it.h"
#include "main.h"

extern uint8_t HEADER_ADDRESS_Write = (((SLAVE_ADDRESS & 0xFF00) >> 7) | 0xF0);
extern uint8_t HEADER_ADDRESS_Read;
/* Private variables ---------------------------------------------------------*/
__IO uint8_t TxBuffer[BUFFERSIZE];
__IO uint8_t Slave_Buffer_Rx[5];
unsigned char m;
extern __IO uint8_t NumOfBytes;
extern __IO uint8_t Tx_Idx;
extern unsigned char IIC_STA ;
extern __IO uint8_t SL_Rx_Idx ;
extern __IO uint8_t  SL_Tx_Idx;

INTERRUPT_HANDLER(I2C1_SPI2_IRQHandler, 29)
{
  m++;
  if(IIC_STA == 1)
  {
  switch (I2C_GetLastEvent(I2C1))
  {
      /* EV5 */
    case I2C_EVENT_MASTER_MODE_SELECT :
      
      /* Send slave Address for write */
      I2C_Send7bitAddress(I2C1, SLAVE_ADDRESS, I2C_Direction_Transmitter);
      break;

      /* EV6 */
    case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
      if (NumOfBytes != 0)
      {
        /* Send the first Data */
        I2C_SendData(I2C1, TxBuffer[Tx_Idx++]);

        /* Decrement number of bytes */
        NumOfBytes--;
      }
      if (NumOfBytes == 0)
      {
        I2C_ITConfig(I2C1, I2C_IT_BUF, DISABLE);
      }
      break;

      /* EV8 */
    case I2C_EVENT_MASTER_BYTE_TRANSMITTING:
      /* Transmit Data */
      I2C_SendData(I2C1, TxBuffer[Tx_Idx++]);

      /* Decrement number of bytes */
      NumOfBytes--;

      if (NumOfBytes == 0)
      {
        I2C_ITConfig(I2C1, I2C_IT_BUF, DISABLE);
      }
      break;

      /* EV8_2 */
    case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
      /* Send STOP condition */
      I2C_GenerateSTOP(I2C1, ENABLE);

      I2C_ITConfig(I2C1, I2C_IT_EVT, DISABLE);
      break;

    default:
      break;
  }
  }
  else
  {
     /* Read SR2 register to get I2C error */
  if (I2C_ReadRegister(I2C1, I2C_Register_SR2))
  {
    /* Clears SR2 register */
    I2C1->SR2 = 0;
  }  
  switch (I2C_GetLastEvent(I2C1))
  {
      /******* Slave transmitter ******/
      /* check on EV1 */
    case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:
      SL_Tx_Idx = 0;
      break;

      /* check on EV3 */
    case I2C_EVENT_SLAVE_BYTE_TRANSMITTING:
      I2C_SendData(I2C1, 0x22);
      break;
      /******* Slave receiver **********/
      /* check on EV1*/
    case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
      break;

      /* Check on EV2*/
    case I2C_EVENT_SLAVE_BYTE_RECEIVED:
      Slave_Buffer_Rx[SL_Rx_Idx++] = I2C_ReceiveData(I2C1);
      break;

      /* Check on EV4 */
    case (I2C_EVENT_SLAVE_STOP_DETECTED):
            /* write to CR2 to clear STOPF flag */
            I2C1->CR2 |= I2C_CR2_ACK;
            SL_Rx_Idx=0;
      break;

    default:
      break;
  }
  }
}

现象
发帖.jpg (179.57 KB, 下载次数: 2) 下载附件 通信现象 2014-2-10 16:18 上传

代码
代码.rar (5.45 KB, 下载次数: 160) 2014-2-10 16:20 上传 点击文件名下载附件
代码




友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
52条回答
lovepig200
1楼-- · 2019-12-30 09:00
lovepig200 发表于 2014-5-5 19:59
你用的模拟 iic么?

你在读的时候为什么发了两次地址?紧接着就是一个nack和stop?

如果你用模拟IIC 作为从机 在中断程序里你一定要做好状态判断,然后在中断函数中 进行 ACK ,NACK等操作。
lovepig200
2楼-- · 2019-12-30 09:49
 精彩回答 2  元偷偷看……
dhw5qq
3楼-- · 2019-12-30 15:40
不啊,我就是主机发命令给从机,从机然后把数据发给主机,

现在主机收到的数据是ff,我不知道为什么没有发出去
dhw5qq
4楼-- · 2019-12-30 16:30
你看嘛,  我现在发命令给从机后,从机已经收到命令了,但是从机发数据的时候,就不对了!ack是从机硬件发的啊,nack是主机读取完数据后发给从机的啊,你看,时序都没有问题的额!
dhw5qq
5楼-- · 2019-12-30 19:22
这个协议不是我自己杜撰的,因为我用avr已经调试好了,但是现在用在这个就出现这个问题!
dhw5qq
6楼-- · 2019-12-30 23:50
lovepig200 发表于 2014-5-5 20:10
作为从机要判断的事件有。

start

谢谢调出来 了,居然是读2遍,奇怪!
  1. u8 read_gasgauge(void)
  2. {
  3.      u8 temp=0,a;
  4.      I2C_start();        
  5.           delay_us(1);
  6.          I2C_write(bq3050_read_address);         
  7.          a=I2C_read(1);         
  8.           temp=I2C_read(0);
  9.          I2C_stop();
  10.          return temp;
  11. }
复制代码

一周热门 更多>