1.頭文件
/*
* one_wire_serial.h
*
* Created on: 2024年5月9日
* Author: Administrator
*/
#ifndef MAIN_ONE_WIRE_SERIAL_H_
#define MAIN_ONE_WIRE_SERIAL_H_
#include <stdint.h>
void one_wire_timer_init(void);
uint8_t one_wire_serial_send_data(uint8_t* data, uint32_t len);
void wire_gpio_init(void);
void test_gpio_init(void);
void report_wire_info(void);
#endif /* MAIN_ONE_WIRE_SERIAL_H_ */
2.源文件
/*
* one_wire_serial.c
*
* Created on: 2024年5月9日
* Author: Administrator
*/
#include "one_wire_serial.h"
#include "driver/timer.h"
#include "driver/gpio.h"
#include "string.h"
#define ENABLE_TEST_GPIO 0
#define WIRE_GPIO_PIN GPIO_NUM_11
#define TEST_GPIO_PIN GPIO_NUM_5
#define ONE_WIRE_SERIAL_TX_BUF_SIZE 1024
#define ONE_WIRE_SERIAL_RX_BUF_SIZE 1024
#define ONE_WIRE_SERIAL_BAUD 9600
#define ONE_WIRE_SERIAL_PLUS_TIME (1000000 / 9600) //US
enum{
ONE_WIRE_SERIAL_RX = 0,
ONE_WIRE_SERIAL_TX,
};
typedef struct{
/*發送數據緩存*/
uint8_t tx_buf[ONE_WIRE_SERIAL_TX_BUF_SIZE];
/*發送字節數據計數*/
uint32_t tx_count;
/*發送長度*/
uint32_t tx_len;
/*發送bit數據計數*/
uint8_t tx_bit_count;
//uint8_t tx_flag;
/*接收數據緩存*/
uint8_t rx_buf[ONE_WIRE_SERIAL_RX_BUF_SIZE];
/*已接收數據長度*/
uint32_t rx_len;
/*接收bit數據計數*/
uint8_t rx_bit_count;
/*接收起始標誌位*/
uint8_t rx_start_flag;
uint8_t status;
}one_wire_serial_t;
one_wire_serial_t oserial = {
.rx_bit_count = 0,
.rx_len = 0,
.rx_start_flag = 0,
.status = ONE_WIRE_SERIAL_RX,
.tx_bit_count = 0,
.tx_count = 0,
.tx_len = 0,
};
#define TIMER_DIVIDER (80) // Hardware timer clock divider
#define WIRE_TIMER_GROUP TIMER_GROUP_0
#define WIRE_TIMER TIMER_0
//開始定時器工作,設定中斷時間us
void one_wire_timer_start(uint32_t us)
{
timer_set_alarm_value(WIRE_TIMER_GROUP, WIRE_TIMER, us);
timer_set_counter_value(WIRE_TIMER_GROUP, WIRE_TIMER, 0);
timer_start(WIRE_TIMER_GROUP, WIRE_TIMER);
}
//停止定時器工作
void one_wire_timer_stop(void)
{
timer_pause(WIRE_TIMER_GROUP, WIRE_TIMER);
}
//設置gpio電平
void set_wire_level(uint8_t level)
{
gpio_set_level(WIRE_GPIO_PIN, level);
}
//0:輸入 1:輸出
void wire_init(uint8_t mode)
{
if(mode)
{
gpio_intr_disable(WIRE_GPIO_PIN);
gpio_set_direction(WIRE_GPIO_PIN, GPIO_MODE_OUTPUT);
}
else
{
gpio_set_direction(WIRE_GPIO_PIN, GPIO_MODE_INPUT);
gpio_intr_enable(WIRE_GPIO_PIN);
}
}
//獲取gpio電平
uint8_t get_wire_level(void)
{
return gpio_get_level(WIRE_GPIO_PIN);
}
//翻轉測試gpio電平
void test_gpio_toggle(void)
{
static uint8_t status = 0;
status = !status;
gpio_set_level(TEST_GPIO_PIN, status);
}
//gpio中斷
void IRAM_ATTR wire_int(void* arg)
{
/*處於接收狀態且沒有開始接收*/
if((oserial.status == ONE_WIRE_SERIAL_RX) && (oserial.rx_start_flag == 0))
{
oserial.rx_start_flag = 1;
one_wire_timer_start(ONE_WIRE_SERIAL_PLUS_TIME / 2);
#if ENABLE_TEST_GPIO
test_gpio_toggle();
#endif
}
//printf("init.\r\n");
}
/*測試gpio初始化*/
void test_gpio_init(void)
{
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << TEST_GPIO_PIN), // 選擇
.mode = GPIO_MODE_OUTPUT, // 設置爲輸入模式
.pull_up_en = GPIO_PULLUP_ENABLE, // 禁用上拉
.pull_down_en = GPIO_PULLDOWN_DISABLE, // 啓用下拉
.intr_type = GPIO_INTR_DISABLE // 禁用中斷
};
gpio_config(&io_conf);
test_gpio_toggle();
}
/*串口gpio初始化*/
void wire_gpio_init(void)
{
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << WIRE_GPIO_PIN), // 選擇GPIO4
.mode = GPIO_MODE_INPUT, // 設置爲輸入模式
.pull_up_en = GPIO_PULLUP_ENABLE, // 禁用上拉
.pull_down_en = GPIO_PULLDOWN_DISABLE, // 啓用下拉
.intr_type = GPIO_INTR_NEGEDGE // 禁用中斷
};
gpio_config(&io_conf);
gpio_install_isr_service(0);
gpio_isr_handler_add(WIRE_GPIO_PIN, wire_int, NULL);
#if ENABLE_TEST_GPIO
test_gpio_init();
#endif
}
/*定時器中斷收發處理*/
void IRAM_ATTR one_wire_serial_handle(void* args)
{
if(oserial.status == ONE_WIRE_SERIAL_TX)//發送模式
{
/*有數據要發送,且還未發完*/
if((oserial.tx_len > 0) && (oserial.tx_count < oserial.tx_len))
{
/*發送起始bit*/
if(oserial.tx_bit_count == 0)
{
set_wire_level(0);
oserial.tx_bit_count++;
}/*發送停止bit*/
else if(oserial.tx_bit_count == 9)
{
set_wire_level(1);
oserial.tx_count++;
oserial.tx_bit_count = 0;
}
else/*發送數據8bit*/
{
set_wire_level((oserial.tx_buf[oserial.tx_count] & (1 << (oserial.tx_bit_count - 1))) ? 1 : 0 );
oserial.tx_bit_count++;
}
}
else
{
oserial.tx_len = 0;
oserial.tx_bit_count = 0;
oserial.tx_count = 0;
oserial.status = ONE_WIRE_SERIAL_RX;
one_wire_timer_stop();
wire_init(0);
}
}
else
{
if(oserial.rx_bit_count == 0)
{
if(get_wire_level() == 0) //起始bit
{
oserial.rx_bit_count++;
one_wire_timer_start(ONE_WIRE_SERIAL_PLUS_TIME);
#if ENABLE_TEST_GPIO
test_gpio_toggle();
#endif
}
else
{
one_wire_timer_stop();
oserial.rx_start_flag = 0;
}
}
else if(oserial.rx_bit_count == 9)
{
if(get_wire_level() == 1) //停止bit
{
oserial.rx_len++;
oserial.rx_bit_count = 0;
}
else
{
oserial.rx_bit_count = 0;
}
#if ENABLE_TEST_GPIO
test_gpio_toggle();
#endif
one_wire_timer_stop();
wire_init(0);
oserial.rx_start_flag = 0;
}
else
{
#if ENABLE_TEST_GPIO
test_gpio_toggle();
#endif
if(get_wire_level())
{
oserial.rx_buf[oserial.rx_len] |= (1 << (oserial.rx_bit_count - 1));
}
else
{
oserial.rx_buf[oserial.rx_len] &= ~(1 << (oserial.rx_bit_count - 1));
}
oserial.rx_bit_count++;
}
}
}
uint8_t one_wire_serial_send_data(uint8_t* data, uint32_t len)
{
if(oserial.tx_len == 0)
{
wire_init(1);
oserial.tx_len = len;
oserial.tx_bit_count = 0;
oserial.tx_count = 0;
oserial.status = ONE_WIRE_SERIAL_TX;
memcpy(oserial.tx_buf, data, len);
one_wire_timer_start(ONE_WIRE_SERIAL_PLUS_TIME);
return 1;
}
return 0;
}
void one_wire_timer_init(void)
{
timer_config_t config = {
.divider = TIMER_DIVIDER,
.counter_dir = TIMER_COUNT_UP,
.counter_en = TIMER_PAUSE,
.alarm_en = TIMER_ALARM_EN,
.auto_reload = TIMER_AUTORELOAD_EN,
}; // default clock source is APB
timer_init(WIRE_TIMER_GROUP, WIRE_TIMER, &config);
timer_set_counter_value(WIRE_TIMER_GROUP, WIRE_TIMER, 0);
timer_isr_callback_add(WIRE_TIMER_GROUP, WIRE_TIMER, one_wire_serial_handle, NULL, 0);
}
void report_wire_info(void)
{
uint64_t value = 0;
timer_get_counter_value(WIRE_TIMER_GROUP, WIRE_TIMER, &value);
//printf("timer count:%lld.\r\n", value);
//printf("oserial.tx_len:%d.\r\n", oserial.tx_len);
//printf("oserial.rx_len:%d.\r\n", oserial.rx_len);
//printf("get_wire_level:%d.\r\n", get_wire_level());
if(oserial.rx_len > 0)
{
printf("%.*s.\r\n", oserial.rx_len, oserial.rx_buf);
//printf("oserial.rx_buf:%.*s.\r\n", oserial.rx_len, oserial.rx_buf);
//printf("oserial.rx_buf[0]:%x.\r\n", oserial.rx_buf[0]);
oserial.rx_len = 0;
}
}
注意事項,目前只支持1bit起始位1bit結束位。