ESP32S3單線軟件串口

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結束位。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章