123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- /**
- * @copyright (C) 2017 Melexis N.V.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
- /**
- * As the timings depend heavily on the MCU in use, it is recommended
- * to make sure that the proper timings are achieved. For that purpose
- * an oscilloscope might be needed to strobe the SCL and SDA signals.
- * The Wait(int) function could be modified in order to better
- * trim the frequency. For coarse setting of the frequency or
- * dynamic frequency change using the default function implementation,
- * ‘freqCnt’ argument should be changed – lower value results in
- * higher frequency.
- */
-
- #include "MLX90640_I2C_Driver.h"
- #include "main.h"
- #define SCL_HIGH HAL_GPIO_WritePin(GPIOA,IIC_SCL_Pin,GPIO_PIN_SET)
- #define SCL_LOW HAL_GPIO_WritePin(GPIOA,IIC_SCL_Pin,GPIO_PIN_RESET)
- #define SDA_HIGH HAL_GPIO_WritePin(GPIOA,IIC_SDA_Pin,GPIO_PIN_SET)
- #define SDA_LOW HAL_GPIO_WritePin(GPIOA,IIC_SDA_Pin,GPIO_PIN_RESET)
- // 将 SDA 配置为输入模式
- #define SDA_IN { \
- GPIO_InitTypeDef GPIO_InitStruct = {0}; \
- GPIO_InitStruct.Pin = IIC_SDA_Pin; \
- GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \
- GPIO_InitStruct.Pull = GPIO_NOPULL; \
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); \
- }
- // 将 SDA 配置为输出模式
- #define SDA_OUT { \
- GPIO_InitTypeDef GPIO_InitStruct = {0}; \
- GPIO_InitStruct.Pin = IIC_SDA_Pin; \
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; \
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; \
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); \
- }
- #define sda HAL_GPIO_ReadPin(GPIOA,IIC_SDA_Pin)
- char i2cData[1664] = {0}; // MLX90640_I2CRead
- int I2CSendByte(int8_t);
- void I2CReadBytes(int, char *);
- void I2CStart(void);
- void I2CStop(void);
- void I2CRepeatedStart(void);
- void I2CSendACK(void);
- void I2CSendNack(void);
- int I2CReceiveAck(void);
- void Wait(int);
- static int freqCnt = 5;
- void MLX90640_I2CInit()
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- __HAL_RCC_GPIOA_CLK_ENABLE();
-
- /*Configure GPIO pins : PA9 SCL */
- GPIO_InitStruct.Pin = IIC_SCL_Pin;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-
- /*Configure GPIO pins : PA10 SDA*/
- GPIO_InitStruct.Pin = IIC_SDA_Pin;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-
- HAL_GPIO_WritePin(GPIOA, IIC_SDA_Pin, GPIO_PIN_SET);
- HAL_GPIO_WritePin(GPIOA, IIC_SCL_Pin, GPIO_PIN_SET);
-
- I2CStop();
- }
-
- int MLX90640_I2CRead(uint8_t slaveAddr, uint16_t startAddress,uint16_t nMemAddressRead, uint16_t *data)
- {
- uint8_t sa;
- int ack = 0;
- int cnt = 0;
- int i = 0;
- char cmd[2] = {0,0};
- // char i2cData[1664] = {0};
- uint16_t *p;
-
- p = data;
- sa = (slaveAddr << 1);
- cmd[0] = startAddress >> 8;
- cmd[1] = startAddress & 0x00FF;
-
- I2CStop();
- Wait(freqCnt);
- I2CStart();
- Wait(freqCnt);
-
- ack = I2CSendByte(sa);
- if(ack != 0)
- {
- return -1;
- }
-
- ack = I2CSendByte(cmd[0]);
- if(ack != 0)
- {
- return -1;
- }
-
- ack = I2CSendByte(cmd[1]);
- if(ack != 0)
- {
- return -1;
- }
-
- I2CRepeatedStart();
-
- sa = sa | 0x01;
-
- ack = I2CSendByte(sa);
- if(ack != 0)
- {
- return -1;
- }
-
- I2CReadBytes((nMemAddressRead << 1), i2cData);
-
- I2CStop();
- for(cnt=0; cnt < nMemAddressRead; cnt++)
- {
- i = cnt << 1;
- *p++ = ((int16_t)i2cData[i]<<8 )|(int16_t)i2cData[i+1];
- // *p++ = (int)i2cData[i]*256 + (int)i2cData[i+1];
- }
- return 0;
-
- }
- void MLX90640_I2CFreqSet(int freq)
- {
- freqCnt = freq>>1;
- }
- int MLX90640_I2CWrite(uint8_t slaveAddr, uint16_t writeAddress, uint16_t data)
- {
- uint8_t sa;
- int ack = 0;
- char cmd[4] = {0,0,0,0};
- static uint16_t dataCheck;
- sa = (slaveAddr << 1);
- cmd[0] = writeAddress >> 8;
- cmd[1] = writeAddress & 0x00FF;
- cmd[2] = data >> 8;
- cmd[3] = data & 0x00FF;
- I2CStop();
- Wait(freqCnt);
- I2CStart();
- ack = I2CSendByte(sa);
- if (ack != 0x00)
- {
- return 1;
- }
-
- for(int i = 0; i<4; i++)
- {
- ack = I2CSendByte(cmd[i]);
-
- if (ack != 0x00)
- {
- return -1;
- }
- }
- I2CStop();
-
- MLX90640_I2CRead(slaveAddr,writeAddress,1, &dataCheck);
-
- if ( dataCheck != data)
- {
- return -2;
- }
-
- return 0;
- }
- int I2CSendByte(int8_t data)
- {
- int ack = 1;
- int8_t byte = data;
- // SDA_OUT;
- for(int i=0;i<8;i++)
- {
- Wait(freqCnt);
-
- if(byte & 0x80)
- {
- SDA_HIGH;
- }
- else
- {
- SDA_LOW;
- }
- Wait(freqCnt);
- SCL_HIGH;
- Wait(freqCnt);
- Wait(freqCnt);
- SCL_LOW;
- byte = byte<<1;
- }
-
- Wait(freqCnt);
- ack = I2CReceiveAck();
-
- return ack;
- }
- void I2CReadBytes(int nBytes, char *dataP)
- {
- char data;
- for(int j=0;j<nBytes;j++)
- {
- Wait(freqCnt);
- // SDA_IN;
-
- data = 0;
- for(int i=0;i<8;i++){
- Wait(freqCnt);
- SCL_HIGH;
- Wait(freqCnt);
- data = data<<1;
- if(sda == 1){
- data = data+1;
- }
- Wait(freqCnt);
- SCL_LOW;
- Wait(freqCnt);
- }
-
- if(j == (nBytes-1))
- {
- I2CSendNack();
- }
- else
- {
- I2CSendACK();
- }
-
- *(dataP+j) = data;
- }
-
- }
-
- void Wait(int freqCnt)
- {
- int cnt;
- // for(int i = 0;i<freqCnt;i++)
- // {
- // cnt = cnt++;
- // }
- while(freqCnt--)
- for(cnt=7;cnt>0;cnt--);
- }
- void I2CStart(void)
- {
- // SDA_OUT;
- SDA_HIGH;
- SCL_HIGH;
- Wait(freqCnt);
- Wait(freqCnt);
- SDA_LOW;
- Wait(freqCnt);
- SCL_LOW;
- Wait(freqCnt);
-
- }
- void I2CStop(void)
- {
- // SDA_OUT;
- SCL_LOW;
- SDA_LOW;
- Wait(freqCnt);
- SCL_HIGH;
- Wait(freqCnt);
- SDA_HIGH;
- Wait(freqCnt);
- }
-
- void I2CRepeatedStart(void)
- {
- // SDA_OUT;
- SCL_LOW;
- Wait(freqCnt);
- SDA_HIGH;
- Wait(freqCnt);
- SCL_HIGH;
- Wait(freqCnt);
- SDA_LOW;
- Wait(freqCnt);
- SCL_LOW;
-
- }
- void I2CSendACK(void)
- {
- // SDA_OUT;
- SDA_LOW;
- Wait(freqCnt);
- SCL_HIGH;
- Wait(freqCnt);
- Wait(freqCnt);
- SCL_LOW;
- Wait(freqCnt);
- SDA_HIGH;
-
- }
- void I2CSendNack(void)
- {
- // SDA_OUT;
- SDA_HIGH;
- Wait(freqCnt);
- SCL_HIGH;
- Wait(freqCnt);
- Wait(freqCnt);
- SCL_LOW;
- Wait(freqCnt);
- SDA_HIGH;
-
- }
- int I2CReceiveAck(void)
- {
- int ack;
-
- // SDA_IN;
- Wait(freqCnt);
- SCL_HIGH;
- Wait(freqCnt);
- if(sda == 0)
- {
- ack = 0;
- }
- else
- {
- ack = 1;
- }
- Wait(freqCnt);
- SCL_LOW;
- SDA_LOW;
-
- return ack;
- }
|