我刚刚开始使用 STM32F103 和 FreeRTOS + Libopencm3 了解嵌入式世界(在 Arduino、RPi 等之后)。我的第一个挑战是将温度传感器 DS18B20 与我的微处理器连接。1-Wire 总线很容易理解,但不受本机支持,因此我按照您的建议使用 1-wire over UART 和 DMA。
DS18B20 在 USART2TX(+4k7 上拉 + 二极管)和 USART2RX 上有 DATA,VCC 到 5V 和 GND。
1-Wire 的初始化:
static void ow_init(void)
{
// One-Wire
// Already done : rcc_periph_clock_enable(RCC_GPIOA);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_USART2_RX);
usart_set_baudrate(USART2, 115200);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_mode(USART2, USART_MODE_TX);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
usart_enable(USART2);
rcc_periph_clock_enable(RCC_DMA1);
}
1线复位:
uint8_t ow_reset(void)
{
usart_disable_rx_dma(USART2);
usart_disable_tx_dma(USART2);
usart_set_baudrate(USART2, 9600);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_mode(USART2, USART_MODE_TX);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
usart_send(USART2, 0xf0);
while(usart_get_flag(USART2, USART_SR_TC));
uint8_t ow_presence;
ow_presence = usart_recv(USART2);
usart_set_baudrate(USART2, 115200);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_mode(USART2, USART_MODE_TX_RX);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
if(ow_presence != 0xf0)
{
return 1;
}
return 0;
}
获取暂存器:
void ow_convert_to_scratchpad(void)
{
const uint8_t convert_T[] = {0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, // 0xCC
0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00}; // 0x44
dma_channel_reset(DMA1, DMA_CHANNEL7);
dma_set_peripheral_address(DMA1, DMA_CHANNEL7, (uint32_t)&USART2_DR);
dma_set_memory_address(DMA1, DMA_CHANNEL7, (uint32_t) convert_T);
dma_set_number_of_data(DMA1, DMA_CHANNEL7, sizeof(convert_T));
dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL7);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL7);
dma_set_peripheral_size(DMA1, DMA_CHANNEL7, DMA_CCR_PSIZE_8BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL7, DMA_CCR_MSIZE_8BIT);
dma_set_priority(DMA1, DMA_CHANNEL7, DMA_CCR_PL_LOW);
dma_enable_channel(DMA1, DMA_CHANNEL7);
usart_enable_tx_dma(USART2);
}
uint16_t ow_get_scratchpad(void)
{
const uint8_t read_scratch[] = {0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, // 0xCC
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, // 0xBE
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t buf[8];
dma_channel_reset(DMA1, DMA_CHANNEL6);
dma_set_peripheral_address(DMA1, DMA_CHANNEL6, (uint32_t)&USART2_DR);
dma_set_memory_address(DMA1, DMA_CHANNEL6, (uint32_t) buf);
dma_set_read_from_peripheral(DMA1, DMA_CHANNEL6);
dma_set_number_of_data(DMA1, DMA_CHANNEL6, sizeof(read_scratch));
dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL6);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL6);
dma_set_peripheral_size(DMA1, DMA_CHANNEL6, DMA_CCR_PSIZE_8BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL6, DMA_CCR_MSIZE_8BIT);
dma_set_priority(DMA1, DMA_CHANNEL6, DMA_CCR_PL_LOW);
dma_channel_reset(DMA1, DMA_CHANNEL7);
dma_set_peripheral_address(DMA1, DMA_CHANNEL7, (uint32_t)&USART2_DR);
dma_set_memory_address(DMA1, DMA_CHANNEL7, (uint32_t) read_scratch);
dma_set_number_of_data(DMA1, DMA_CHANNEL7, sizeof(read_scratch));
dma_set_read_from_peripheral(DMA1, DMA_CHANNEL6);
dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL7);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL7);
dma_set_peripheral_size(DMA1, DMA_CHANNEL7, DMA_CCR_PSIZE_8BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL7, DMA_CCR_MSIZE_8BIT);
dma_set_priority(DMA1, DMA_CHANNEL7, DMA_CCR_PL_LOW);
dma_enable_channel(DMA1, DMA_CHANNEL6);
dma_enable_channel(DMA1, DMA_CHANNEL7);
usart_enable_tx_dma(USART2);
usart_enable_rx_dma(USART2);
while(dma_get_interrupt_flag(DMA1, DMA_CHANNEL6, DMA_TCIF));
uint16_t tt = 0;
for(int i=0;i<32; i++)
{
uart1_printf("Bit : %d \n\r", buf[i]);
if(buf[i] == 0xff)
{
tt = (tt >> 1) | 0x8000;
}
else
{
tt = tt >> 1;
}
}
return tt;
}
static void demo_task(void *args)
{
(void)args;
for (;;) {
uart1_printf("Hello\n\r");
uint8_t p = ow_reset();
uart1_printf("presence = %d\n\r", p);
ow_convert_to_scratchpad();
for(int i=0; i<5000000; i++)
{
__asm__("nop");
}
ow_reset();
uint16_t t = ow_get_scratchpad();
uart1_printf("t = %d \n\r", t);
vTaskDelay(pdMS_TO_TICKS(500));
}
}
最后是试图到达 DS18B20 的任务
static void demo_task(void *args)
{
(void)args;
for (;;) {
ow_reset();
ow_convert_to_scratchpad();
vTaskDelay(pdMS_TO_TICKS(500));
ow_reset();
uint16_t t = ow_get_scratchpad();
uart1_printf("t = %d \n\r", t);
vTaskDelay(pdMS_TO_TICKS(500));
}
}
我收到一些位 0xCC、0xBE、0xFF 但没有更多答案。