123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- #include "board.h"
- typedef struct
- {
- uint32_t tx_port;
- uint8_t tx_pin;
- uint8_t tx_pin_af;
- uint32_t rx_port;
- uint8_t rx_pin;
- uint8_t rx_pin_af;
- uint32_t rs485_port;
- unsigned short rs485_pin;
- } hw_uart_pin_t;
- typedef struct
- {
- uint32_t base; //串口对像
- uint32_t speed; //通讯速度
- dma_channel_enum rx_dma_stream; //接收所在的DMA
- dma_channel_enum tx_dma_stream; //接收所在的DMA
- int rx_timeout; //接收空闲时间
- int tx_endtime; //发送完毕后多少时候算完成
- unsigned short rx_length; //接收长度
- unsigned short dma_value; //上次DMA接收的长度值
- sw_timer_t recv_timer;
- sw_timer_t send_timer;
- } hw_dma_uart_t;
- //管脚配置
- //管脚功能复用,需要自己去查找数据手册
- static hw_uart_pin_t hw_uart_pins_map[HW_DMA_UART_NUMBER] = {
- { GPIOA, 9, GPIO_AF_1, GPIOA, 10, GPIO_AF_1, 0, 0 },
- { GPIOA, 2, GPIO_AF_1, GPIOA, 3, GPIO_AF_1, GPIOC, 15 }
- };
- //串口配置
- //DMA对应的数据流通道,可以查找手册查到
- static hw_dma_uart_t hw_uarts_map[HW_DMA_UART_NUMBER] = {
- { USART0, 115200, DMA_CH2, DMA_CH1, 2000, 0 },
- { USART1, 19200, DMA_CH4, DMA_CH3, 2000, 0 }
- };
- #define RS485_RX_ENABLE(port,pin) GPIO_BOP(port) = 1 << (pin + 16)
- #define RS485_TX_ENABLE(port,pin) GPIO_BOP(port) = 1 << pin
- static int current_core_freq = 1;
- void hw_dma_uart_init(int clk) {
- int index = 0;
- //使能DMA时钟
- rcu_periph_clock_enable(rcu_periph_clock_bit(DMA));
- for (index = 0; index < HW_DMA_UART_NUMBER; index++) {
- uint32_t port = (uint32_t)hw_uart_pins_map[index].rx_port;
- uint16_t pin = 1 << hw_uart_pins_map[index].rx_pin;
- uint8_t af = hw_uart_pins_map[index].rx_pin_af;
- if (port != 0) {
- //使能时钟
- rcu_periph_clock_enable(rcu_periph_clock_bit(port));
- //配置IO为输出
- gpio_mode_set(port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, pin);
- gpio_output_options_set(port, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, pin);
- gpio_af_set(port, af, pin);
- }
- port = (uint32_t)hw_uart_pins_map[index].tx_port;
- pin = 1 << hw_uart_pins_map[index].tx_pin;
- af = hw_uart_pins_map[index].tx_pin_af;
- if (port != 0) {
- //使能时钟
- rcu_periph_clock_enable(rcu_periph_clock_bit(port));
- //配置IO为输出
- gpio_mode_set(port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, pin);
- gpio_output_options_set(port, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, pin);
- gpio_af_set(port, af, pin);
- }
- port = (uint32_t)hw_uart_pins_map[index].rs485_port;
- pin = 1 << hw_uart_pins_map[index].rs485_pin;
- if (port != 0) {
- //使能时钟
- rcu_periph_clock_enable(rcu_periph_clock_bit(port));
- //配置IO为输出
- gpio_mode_set(port, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, pin);
- gpio_output_options_set(port, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, pin);
- }
- }
- for (index = 0; index < HW_DMA_UART_NUMBER; index++) {
- uint32_t base = (uint32_t)hw_uarts_map[index].base;
- //设置跟随波特率
- hw_noinit_write(2 * index + 2,hw_uarts_map[index].speed);
- //使能串口时钟
- rcu_periph_clock_enable(rcu_periph_clock_bit(base));
- //复位串口
- usart_deinit(base);
- //设置波特率
- usart_baudrate_set(base, hw_uarts_map[index].speed);
- //使能接收
- usart_receive_config(base, USART_RECEIVE_ENABLE);
- //使能发送
- usart_transmit_config(base, USART_TRANSMIT_ENABLE);
- //8位长度
- usart_word_length_set(base, 8);
- //1位停止位
- usart_stop_bit_set(base, 1);
- //使能串口
- usart_enable(base);
- {
- dma_channel_enum channelx = hw_uarts_map[index].rx_dma_stream;
- uint32_t ctl;
- //复位DMA配置
- dma_deinit(channelx);
- //通道禁止
- dma_channel_disable(channelx);
- //外设地址
- DMA_CHPADDR(channelx) = hw_uarts_map[index].base + 0x24;
- //内存地址,暂时不需要
- DMA_CHMADDR(channelx) = 0x20000000;
- //要传送的数量
- DMA_CHCNT(channelx) = (0 & DMA_CHANNEL_CNT_MASK);
- //清除DMA配置寄存器
- ctl = DMA_CHCTL(channelx);
- ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO | DMA_CHXCTL_PNAGA);
- //禁止外设地址递增
- ctl &= ~(DMA_CHXCTL_PNAGA);
- //禁止循环模式
- ctl &= ~(DMA_CHXCTL_CMEN);
- //禁止内存到内存模式
- ctl &= ~(DMA_CHXCTL_M2M);
- //设置DMA的位宽与优先级,设置内存地址递增
- ctl |= (DMA_PERIPHERAL_WIDTH_8BIT | DMA_MEMORY_WIDTH_8BIT | DMA_PRIORITY_ULTRA_HIGH);
- //使能内存地址递增
- ctl |= DMA_CHXCTL_MNAGA;
- //方向为外设进内存
- ctl &= ~(DMA_CHXCTL_DIR);
- DMA_CHCTL(channelx) = ctl;
- //使能DMA接收
- //usart_dma_receive_config(hw_uarts_map[index].base, USART_DENR_ENABLE);
- //使能DMA通道
- //DMA_CHCTL(channelx) |= DMA_CHXCTL_CHEN;
- channelx = hw_uarts_map[index].tx_dma_stream;
- //复位DMA配置
- dma_deinit(channelx);
- //通道禁止
- dma_channel_disable(channelx);
- //外设地址
- DMA_CHPADDR(channelx) = hw_uarts_map[index].base + 0x28;
- //内存地址,暂时不需要
- DMA_CHMADDR(channelx) = 0x20000000;
- //要传送的数量
- DMA_CHCNT(channelx) = (0 & DMA_CHANNEL_CNT_MASK);
- //清除DMA配置寄存器
- ctl = DMA_CHCTL(channelx);
- ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO | DMA_CHXCTL_PNAGA);
- //禁止外设地址递增
- ctl &= ~(DMA_CHXCTL_PNAGA);
- //禁止循环模式
- ctl &= ~(DMA_CHXCTL_CMEN);
- //禁止内存到内存模式
- ctl &= ~(DMA_CHXCTL_M2M);
- //设置DMA的位宽与优先级,设置内存地址递增
- ctl |= (DMA_PERIPHERAL_WIDTH_8BIT | DMA_MEMORY_WIDTH_8BIT | DMA_PRIORITY_ULTRA_HIGH);
- //使能内存地址递增
- ctl |= DMA_CHXCTL_MNAGA;
- //方向为内存到外设
- ctl |= (DMA_CHXCTL_DIR);
- DMA_CHCTL(channelx) = ctl;
- //使能DMA发送
- //usart_dma_receive_config(hw_uarts_map[index].base, USART_DENT_ENABLE);
- //使能DMA通道
- //DMA_CHCTL(channelx) |= DMA_CHXCTL_CHEN;
- //默认485是接收模式
- if (hw_uart_pins_map[index].rs485_port != 0) {
- RS485_RX_ENABLE(hw_uart_pins_map[index].rs485_port, hw_uart_pins_map[index].rs485_pin);
- }
- }
- }
- }
- /**
- * 读取串口缓冲,
- *
- * @author lxz
- *
- * @param uart_index 串口编号
- * @param buffer 读取数据的缓冲
- * @param size 读取的最大长度
- *
- * @return int 实际读取数量
- */
- int hw_dma_uart_begin_read(unsigned char uart_index, unsigned char *buffer, int size) {
- if (uart_index < HW_DMA_UART_NUMBER && size > 0){
- dma_channel_enum channelx = hw_uarts_map[uart_index].rx_dma_stream;
- //通道禁止
- dma_channel_disable(channelx);
- //清除所有标志
- dma_interrupt_flag_clear(channelx, DMA_INT_FLAG_G);
- //内存地址
- DMA_CHMADDR(channelx) = (uint32_t)buffer;
- //传输大小
- DMA_CHCNT(channelx) = (size & DMA_CHANNEL_CNT_MASK);
- //使能DMA
- dma_channel_enable(channelx);
- //使能串口DMA接口
- usart_dma_receive_config(hw_uarts_map[uart_index].base, USART_DENR_ENABLE);
- hw_uarts_map[uart_index].rx_length = size;
- //进入接收模式
- if (hw_uart_pins_map[uart_index].rs485_port != 0) {
- RS485_RX_ENABLE(hw_uart_pins_map[uart_index].rs485_port, hw_uart_pins_map[uart_index].rs485_pin);
- }
- }
- return 0;
- }
- /**
- * 输出到串口缓冲
- *
- * @author lxz
- *
- * @param uart_index 串口编号
- * @param buffer 发送数据的缓冲
- * @param size 发送的数据长度
- *
- * @return int 实际发送的数据长度
- *
- */
- int hw_dma_uart_begin_write(unsigned char uart_index, const char *buffer, int size) {
- if (uart_index < HW_DMA_UART_NUMBER && size > 0){
- dma_channel_enum channelx = hw_uarts_map[uart_index].tx_dma_stream;
- //通道禁止
- dma_channel_disable(channelx);
- //清除所有标志
- dma_interrupt_flag_clear(channelx, DMA_INT_FLAG_G);
- //内存地址
- DMA_CHMADDR(channelx) = (uint32_t)buffer;
- //传输大小
- DMA_CHCNT(channelx) = (size & DMA_CHANNEL_CNT_MASK);
- //使能DMA
- dma_channel_enable(channelx);
- //使能串口DMA接口
- usart_dma_receive_config(hw_uarts_map[uart_index].base, USART_DENT_ENABLE);
- //进入接收模式
- if (hw_uart_pins_map[uart_index].rs485_port != 0) {
- RS485_TX_ENABLE(hw_uart_pins_map[uart_index].rs485_port, hw_uart_pins_map[uart_index].rs485_pin);
- }
- }
- return 0;
- }
- /**
- * 检查是否读取成功,成功会返回对应长度
- *
- * @author lxz
- *
- * @param void
- *
- * @return int
- */
- int hw_dma_uart_read_finish(unsigned char uart_index) {
- if (uart_index < HW_DMA_UART_NUMBER && hw_uarts_map[uart_index].rx_length > 0) {
- dma_channel_enum channelx = hw_uarts_map[uart_index].rx_dma_stream;
- hw_dma_uart_t * uart = &hw_uarts_map[uart_index];
- int res = DMA_CHCNT(channelx);
- //如果硬件产生了错误,需要手动清除
- if (usart_flag_get(hw_uarts_map[uart_index].base, USART_FLAG_ORERR)) {
- usart_flag_clear(hw_uarts_map[uart_index].base, USART_FLAG_ORERR);
- }
- if (res == 0) {
- res = uart->rx_length - res;
- uart->rx_length = 0;
- //接收完毕,关闭DMA接收使能
- usart_dma_receive_config(hw_uarts_map[uart_index].base, USART_DENR_DISABLE);
- return res;
- } else if (res != uart->dma_value) {
- uart->dma_value = res;
- sw_timer_start(&uart->recv_timer, 0, uart->rx_timeout);
- } else if (uart->rx_length != res &&
- sw_timer_expire(&uart->recv_timer)) {
- //停止接收
- dma_channel_disable(channelx);
- res = uart->rx_length - res;
- uart->rx_length = 0;
- usart_dma_receive_config(hw_uarts_map[uart_index].base, USART_DENR_DISABLE);
- return res;
- }
- }
- return 0;
- }
- /**
- * 检测是否写入成功,写入成功会返回1
- *
- * @author lxz
- *
- * @param void
- *
- * @return int
- */
- int hw_dma_uart_write_finish(unsigned char uart_index) {
- if (uart_index < HW_DMA_UART_NUMBER) {
- hw_dma_uart_t *uart = &hw_uarts_map[uart_index];
- if (usart_flag_get(hw_uarts_map[uart_index].base, USART_FLAG_TC)) {
- if (sw_timer_expire(&uart->send_timer)) {
- //使能脚转接收模式
- if (hw_uart_pins_map[uart_index].rs485_port != 0) {
- RS485_RX_ENABLE(hw_uart_pins_map[uart_index].rs485_port, hw_uart_pins_map[uart_index].rs485_pin);
- }
- return 1;
- }
- } else {
- sw_timer_start(&uart->send_timer, 0, uart->tx_endtime);
- }
- }
- return 0;
- }
- /**
- * 串口一些参数动态设置接口
- *
- * @author lxz
- *
- * @param uart_index
- * @param cmd
- * @param value
- */
- int hw_dma_uart_control(unsigned char uart_index, char cmd, void *value) {
- if (uart_index >= HW_DMA_UART_NUMBER) {
- return -1;
- }
- switch (cmd) {
- case UART_CTRL_RECONFIG : //设置串口速度
- {
- uint32_t base = (uint32_t)hw_uarts_map[uart_index].base;
- hw_uart_config *config = (hw_uart_config *)value;
- usart_disable(base);
- //设置波特率
- usart_baudrate_set(base, config->speed);
- hw_uarts_map[uart_index].speed = config->speed;
- //8位长度
- usart_word_length_set(base, config->databits);
- //1位停止位
- usart_stop_bit_set(base, config->stopbits);
- if (config->parity == 1) {
- usart_parity_config(base, USART_PM_EVEN);
- } else if (config->parity == 2) {
- usart_parity_config(base, USART_PM_ODD);
- } else {
- usart_parity_config(base, USART_PM_NONE);
- }
- //使能串口
- usart_enable(base);
- }
- break;
- case UART_CTRL_SET_RDFIN_TIME : //设置串口接收完成判断时间
- {
- hw_uarts_map[uart_index].rx_timeout = *((int *)value);
- }
- break;
- case UART_CTRL_SET_WRFIN_TIME : //设置串口发送完成判断时间
- {
- hw_uarts_map[uart_index].tx_endtime = *((int *)value);
- }
- break;
- case UART_CTRL_GET_SPEED : //获取当前速度
- {
- return hw_uarts_map[uart_index].speed;
- }
- break;
- case UART_CTRL_GET_RDFIN_TIME : //获取当前串口接收完成时间
- {
- return hw_uarts_map[uart_index].rx_timeout;
- }
- break;
- case UART_CTRL_GET_WRFIN_TIME : //获取当前串口写入完成时间
- {
- return hw_uarts_map[uart_index].tx_endtime;
- }
- break;
- case UART_CTRL_GET_RDFIN : //串口接收是否完成,如果完成会返回接收长度
- {
- return hw_dma_uart_read_finish(uart_index);
- }
- break;
- case UART_CTRL_GET_WRFIN : //串口发送是否完成
- {
- return hw_dma_uart_write_finish(uart_index);
- }
- break;
- default:
- break;
- }
- return 0;
- }
|