#include "myiic.h"
#include "gpio.h"
#include "tim.h"
#include <stdio.h>
#include <string.h>
enum MODE{
INPUT = 0,
OUTPUT,
};
void my_delay_us(uint32_t us){
__HAL_TIM_SET_COUNTER(&htim6, 0);
while(__HAL_TIM_GET_COUNTER(&htim6) < us);
}
void myiic_set_sda_mode(uint8_t mode){
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(mode == INPUT){
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = IIC_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(IIC_SDA_GPIO_Port, &GPIO_InitStruct);
}
if(mode == OUTPUT){
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = IIC_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(IIC_SDA_GPIO_Port, &GPIO_InitStruct);
}
}
void set_sda_high(){
HAL_GPIO_WritePin(IIC_SDA_GPIO_Port, IIC_SDA_Pin, GPIO_PIN_SET);
}
void set_sda_low(){
HAL_GPIO_WritePin(IIC_SDA_GPIO_Port, IIC_SDA_Pin, GPIO_PIN_RESET);
}
void set_scl_high(){
HAL_GPIO_WritePin(IIC_SCL_GPIO_Port, IIC_SCL_Pin, GPIO_PIN_SET);
}
void set_scl_low(){
HAL_GPIO_WritePin(IIC_SCL_GPIO_Port, IIC_SCL_Pin, GPIO_PIN_RESET);
}
uint8_t read_sda(){
return HAL_GPIO_ReadPin(IIC_SDA_GPIO_Port, IIC_SDA_Pin);
}
uint8_t read_scl(){
return HAL_GPIO_ReadPin(IIC_SCL_GPIO_Port, IIC_SCL_Pin);
}
//起始信号,SCL为高电平时候,SDA下降沿为开始
void myiic_start(){
myiic_set_sda_mode(OUTPUT);//设置SCL为输出
set_sda_high();
set_scl_high();
my_delay_us(5);
set_sda_low();
my_delay_us(5);
}
//终止信号,SCL为高电平时候,SDA上升沿为结束
void myiic_stop(){
myiic_set_sda_mode(OUTPUT);//设置SCL为输出
set_sda_low();
set_scl_high();
my_delay_us(5);
set_sda_high();
my_delay_us(5);
}
//读应答 要求
uint8_t myiic_read_ack(){
set_scl_low();//读应答之前将scl拉低,使得sda线可以改变
myiic_set_sda_mode(INPUT);//设置sda为输
set_scl_high();
my_delay_us(5);
if(read_sda()){
set_scl_low();
return 1;
}else{
set_scl_low();
return 0;
}
}
//发送应答
void myiic_send_ack(uint8_t i){
set_scl_low();//将scl拉低sda才能变化
myiic_set_sda_mode(OUTPUT);//设置SCL为输出
if(i){
set_sda_high();
}else{
set_sda_low();
}
set_scl_high();
my_delay_us(5);
// set_scl_low();
// set_sda_high();
}
uint8_t send_byte(uint8_t data){
myiic_set_sda_mode(OUTPUT);//设置SCL为输出
uint8_t i = 0;
uint8_t temp = 0x80;
for(i = 0; i < 8; i++){
set_scl_low();
/*在这段时间里面改变数据*/
if((data & temp) == 0){
set_sda_low();
}else{
set_sda_high();
}
temp >>= 1;
set_scl_high();
// my_delay_us(5);
}
set_scl_low();
}
uint8_t read_byte(){
//将sda设置为输入模式
myiic_set_sda_mode(INPUT);
uint8_t data = 0;
uint8_t i = 0;
uint8_t temp = 0x80;
for(i = 0; i < 8; i++){
set_scl_low();
/*在这段时间里面改变数据*/
// my_delay_us(5);
set_scl_high();
// my_delay_us(5);
data <<= 1;
data |= read_sda();
set_scl_low();
}
return data;
}
void At24c02Write(unsigned char addr,unsigned char dat){
myiic_start();
send_byte(0xa0);//发送写器件地址
if(myiic_read_ack()){
printf("slave not response1\r\n");
}
send_byte(addr);//发送要写入内存地址
if(myiic_read_ack()){
printf("slave not response2\r\n");
}
send_byte(dat); //发送数据
if(myiic_read_ack()){
printf("slave not response3\r\n");
}
myiic_stop();
}
unsigned char At24c02Read(unsigned char addr)
{
uint8_t num;
myiic_start();
send_byte(0xa0); //发送写器件地址
if(myiic_read_ack()){
printf("slave not response4\r\n");
}
send_byte(addr); //发送要读取的地址
if(myiic_read_ack()){
printf("slave not response5\r\n");
}
myiic_start();
send_byte(0xa1); //发送读器件地址
if(myiic_read_ack()){
printf("slave not response6\r\n");
}
num = read_byte(); //读取数据
myiic_send_ack(1);
myiic_stop();
return num;
}
void at24c02_write_string(unsigned char addr, uint8_t* data){
uint8_t i = 0;
for(i = 0; i < strlen(data); i++){
At24c02Write(addr, data[i]);
addr++;
HAL_Delay(1);
}
}
void at24c02_read_string(unsigned char addr, uint8_t* data, uint8_t len){
uint8_t i = 0;
for(i = 0; i < len; i++){
data[i] = At24c02Read(addr);
addr++;
HAL_Delay(1);
}
}