很长一段时间以来,我一直在努力与两种STM32板以某种形式进行DMA通信。我目前的问题如下。
我有一个主机(Raspberry Pi)运行以下代码,等待主板初始化通信:
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
unsigned int usbdev;
unsigned char c;
system("stty -F /dev/ttyUSB0 921600 icanon raw");
usbdev = open("/dev/ttyUSB0", O_RDWR);
setbuf(stdout, NULL);
fprintf(stderr, "Waiting for signal..\n");
while (!read(usbdev, &c, 1));
unsigned char buf[] = "Defend at noon\r\n";
write(usbdev, buf, 16);
fprintf(stderr, "Written 16 bytes\r\n");
while (1) {
while (!read(usbdev, &c, 1));
printf("%c", c);
}
return 0;
}
基本上,在它发送&#34;中午保卫&#34;之前,它会等待一个字节的数据。到董事会之后,它会打印发回的所有内容。
电路板首先发出一个字节,然后等待所有输入数据,替换几个字节并将其发回。请参阅本文末尾的代码。该板可以是STM32L100C或STM32F407(实际上是发现板);我此时遇到了同样的行为。
我看到的输出(在一个美好的一天 - 在一个糟糕的日子它挂起Written 16 bytes
)如下:
Waiting for signal..
Written 16 bytes
^JDefend adawnon
如您所见,数据已发送,并且按预期更换了四个字节,但前面还有两个字符(^J
,0x5E
和{{1} })。结果证明这是0x4A
函数的直接结果。当我用任意的东西替换角色(例如signal_host
)时,那就是在那个位置输出的东西。值得注意的是,x
实际上会在路上的某处转换为其符号符号\n
。这似乎发生在通信到板上,因为当我只是简单地对缓冲区中的字符串进行硬编码并使用^J
将其发送到非交互式主机程序时,它会被打印出来很好。
在某种意义上说,某些缓冲区没有被正确清除,看起来我错误地配置了DMA。另外,我真的不相信主机端程序使用stty的方式。但是,我实际上过去使用这个确切的代码完美地进行了沟通。我将它与几个月内存储在我的git历史中的代码进行了比较,我找不到区别/缺陷。
请注意,以下代码使用libopencm3,并基于libopencm3-examples中的示例。
STM32L1代码:
dma_transmit
STM32F4代码:
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/dma.h>
void clock_setup(void)
{
rcc_clock_setup_pll(&clock_config[CLOCK_VRANGE1_HSI_PLL_32MHZ]);
rcc_periph_clock_enable(RCC_GPIOA);
rcc_periph_clock_enable(RCC_USART2);
rcc_periph_clock_enable(RCC_DMA1);
}
void gpio_setup(void)
{
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2 | GPIO3);
gpio_set_af(GPIOA, GPIO_AF7, GPIO2 | GPIO3);
}
void usart_setup(int baud)
{
usart_set_baudrate(USART2, baud);
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);
usart_enable(USART2);
}
void dma_request_setup(void)
{
dma_channel_reset(DMA1, DMA_CHANNEL6);
nvic_enable_irq(NVIC_DMA1_CHANNEL6_IRQ);
dma_set_peripheral_address(DMA1, DMA_CHANNEL6, (uint32_t) &USART2_DR);
dma_set_read_from_peripheral(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_VERY_HIGH);
dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL6);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL6);
dma_disable_transfer_error_interrupt(DMA1, DMA_CHANNEL6);
dma_disable_half_transfer_interrupt(DMA1, DMA_CHANNEL6);
dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL6);
}
void dma_transmit_setup(void)
{
dma_channel_reset(DMA1, DMA_CHANNEL7);
nvic_enable_irq(NVIC_DMA1_CHANNEL7_IRQ);
dma_set_peripheral_address(DMA1, DMA_CHANNEL7, (uint32_t) &USART2_DR);
dma_set_read_from_memory(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_VERY_HIGH);
dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL7);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL7);
dma_disable_transfer_error_interrupt(DMA1, DMA_CHANNEL7);
dma_disable_half_transfer_interrupt(DMA1, DMA_CHANNEL7);
dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL7);
}
void dma_request(void* buffer, const int datasize)
{
dma_set_memory_address(DMA1, DMA_CHANNEL6, (uint32_t) buffer);
dma_set_number_of_data(DMA1, DMA_CHANNEL6, datasize);
dma_enable_channel(DMA1, DMA_CHANNEL6);
signal_host();
usart_enable_rx_dma(USART2);
}
void dma_transmit(const void* buffer, const int datasize)
{
dma_set_memory_address(DMA1, DMA_CHANNEL7, (uint32_t) buffer);
dma_set_number_of_data(DMA1, DMA_CHANNEL7, datasize);
dma_enable_channel(DMA1, DMA_CHANNEL7);
usart_enable_tx_dma(USART2);
}
int dma_done(void)
{
return !((DMA1_CCR6 | DMA1_CCR7) & 1);
}
void dma1_channel6_isr(void) {
usart_disable_rx_dma(USART2);
dma_clear_interrupt_flags(DMA1, DMA_CHANNEL6, DMA_TCIF);
dma_disable_channel(DMA1, DMA_CHANNEL6);
}
void dma1_channel7_isr(void) {
usart_disable_tx_dma(USART2);
dma_clear_interrupt_flags(DMA1, DMA_CHANNEL7, DMA_TCIF);
dma_disable_channel(DMA1, DMA_CHANNEL7);
}
void signal_host(void) {
usart_send_blocking(USART2, '\n');
}
int main(void)
{
clock_setup();
gpio_setup();
usart_setup(921600);
dma_transmit_setup();
dma_request_setup();
unsigned char buf[16];
dma_request(buf, 16); while (!dma_done());
buf[10] = 'd';
buf[11] = 'a';
buf[12] = 'w';
buf[13] = 'n';
dma_transmit(buf, 16); while (!dma_done());
while(1);
return 0;
}
答案 0 :(得分:1)
好吧,我可以简要介绍一下这个。
我建议不要将stty
用于此类事情。我意识到我可能没有正确配置stty
,并且通过一些选项调整它可能是正确的,但它完全不清楚。我最终将它扔出窗外并使用pyserial代替。我应该在几周前完成这项工作。上面的STM32代码工作正常,所需的Python代码完全无关紧要。
#!/usr/bin/env python3
import serial
dev = serial.Serial("/dev/ttyUSB0", 921600)
dev.read(1) # wait for the signal
dev.write("Defend at noon\r\n".encode('utf-8'))
while True:
x = dev.read()
print(x.decode('utf-8'), end='', flush=True)