Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
RT-Thread的驱动问题
发布于 2014-11-11 08:36:39 浏览:7777
订阅该版
我已经在LPC1768和STM32F107这2个芯片上使用过了RT-Thread 1.2,总体感觉很好,API也很容易使用,最大的问题是设备驱动。bsp包里的驱动只有最简单的串口驱动,其他接口(SPI、I2C,没开始用USB和网络)的驱动更是找不到,为了做项目,自己断断续续花了几个星期完成了USART DMA TX+DMA RX、SPI和I2C接口的代码。 我想问一下前辈们,这些驱动是否已经有人已经实现了,到哪可以找到?
查看更多
16
个回答
默认排序
按发布时间排序
bernard
2014-11-11
这家伙很懒,什么也没写!
这些有些有,有些没有。bsp上根据各个分支维护人的情况,自行选择保留支持的驱动。总的来说,还是尽量选择RT-Thread支持得比较好的平台,例如原来的STM32F4(RealTouch),LPC4088(RealBoard)
虫少耶
2014-11-11
这家伙很懒,什么也没写!
我明白了。 但是这样的话对新接触RT-Thread的人来说,上手门槛比较高,多数芯片一开始就要自己解决驱动问题。 希望RT能早日完善驱动,建议论坛开辟驱动专区,大家一起完善驱动。
bernard
2014-11-11
这家伙很懒,什么也没写!
驱动代码部分,因为RTT是使用github来进行版本控制的,所以大家有驱动程序可以发pull request到github上,在code review后是可以合入发布主干的。
kerrhu
2014-11-14
这家伙很懒,什么也没写!
>我已经在LPC1768和STM32F107这2个芯片上使用过了RT-Thread 1.2,总体感觉很好,API也很容易使用,最大的问题是设备驱动。bsp包里的驱动只有最简单的串口驱动,其他接口(SPI、I2C,没开始用USB和网络)的驱动更是找不到,为了做项目,自己断断续续花了几个星期完成了USART DMA TX+DMA RX、SPI和I2C接口的代码。 > >我想问一下前辈们,这些驱动是否已经有人已经实现了,到哪可以找到? --- ------------- 能不能把你的107驱动发上来参考下
虫少耶
2014-11-25
这家伙很懒,什么也没写!
我的代码写的比较差,项目赶得紧,有些注释也没来得及更新,既然有人需要,发上来仅供参考,抛砖引玉: 一、USART2驱动(USART1~4类似),循环DMA RX,自动DMA TX ``` #include "stm32f10x.h" #include
#include
#include
#include
#include "fifo.h" #include "usart2.h" #include "usart3.h" #define UART2_TX_DMA_CHANNAL DMA1_Channel7 #define UART2_RX_DMA_CHANNAL DMA1_Channel6 /* ********************************************************************************************************* * UART2公有变量 ********************************************************************************************************* */ // Uart2设备指针,全局变量,程序使用Uart2必须通过这个指针 rt_device_t G_Uart2Handle = RT_NULL; /* ********************************************************************************************************* * UART2私有变量 ********************************************************************************************************* */ // 接收和发送FIFO缓冲区 static rt_uint8_t f_uart2_txBuffer[UART2_SW_FIFO_SIZE]; static FIFO f_uart2_txFifo; // 接收和发送DMA缓冲区 static rt_uint8_t f_uart2_dma_txBuffer[UART2_DMA_TXBUF_SIZE]; static rt_uint8_t f_uart2_dma_rxBuffer[UART2_DMA_RXBUF_SIZE]; static uint16_t f_uart2_rxbuf_get_index = 0; volatile uint8_t f_uart2_dma_tx_busy = RT_FALSE; // 标记Uart2是否已经初始化过 static rt_err_t f_Uart2Initialized = RT_FALSE; // Uart2设备控制块 static struct rt_device f_uart2_device; /* ********************************************************************************************************* * 函数声明 ********************************************************************************************************* */ static rt_err_t rt_uart2_init (rt_device_t dev); static void uart2_DMA_Configuration(void); static void uart2_GPIO_Configuration(void); static void uart2_NVIC_Configuration(void); static void USART2_Configuration(void); static rt_err_t rt_uart2_rx_indicate(rt_device_t dev, rt_size_t size); static rt_err_t rt_uart2_open(rt_device_t dev, rt_uint16_t oflag); static rt_err_t rt_uart2_close(rt_device_t dev); static rt_size_t rt_uart2_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size); static rt_size_t rt_uart2_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size); uint32_t is_DMA_channel_enable(DMA_Channel_TypeDef* DMAy_Channelx); static void uart2_DMA_tx_start(uint16_t tx_size); /* ********************************************************************************************************* * UART2公有函数 ********************************************************************************************************* */ void uart2_entry(void* parameter) { rt_uint16_t rx_number; uint8_t buf[64]; if(IsUart2Initialized() == RT_FALSE) { rt_hw_uart2_init(); } rt_kprintf(" uart2_entry Start OK"); while(1) { rx_number = uart2_available(); if(rx_number) { if(rx_number > 64) { rx_number = 64; } rt_device_read (G_Uart2Handle, 0, buf, rx_number); rt_device_write (G_Uart2Handle, 0, buf, rx_number); } rt_thread_delay(1); } } rt_err_t IsUart2Initialized(void) { return f_Uart2Initialized; } /* * * 描述 : 初始化UART2设备 * * 参数 : 无 * * 返回 : 无 * */ void rt_hw_uart2_init(void) { rt_device_t uart; rt_err_t ret; if(f_Uart2Initialized == RT_FALSE) { f_Uart2Initialized = RT_TRUE; } else { return; } // get uart device uart = &f_uart2_device; // 设备类型 uart->type = RT_Device_Class_Char; // 初始化缓冲区 rt_memset(&f_uart2_txBuffer, 0, sizeof(f_uart2_txBuffer)); // 初始化uart2软件fifo fifo_init(&f_uart2_txFifo, UART2_SW_FIFO_SIZE, (uint8_t*)f_uart2_txBuffer); // 初始化dma缓冲区 rt_memset(&f_uart2_dma_txBuffer, 0, sizeof(f_uart2_dma_txBuffer)); rt_memset(&f_uart2_dma_rxBuffer, 0, sizeof(f_uart2_dma_rxBuffer)); // 添加数据接收指示 rt_device_set_rx_indicate(uart, rt_uart2_rx_indicate); /* device interface */ uart->init = rt_uart2_init; uart->open = rt_uart2_open; uart->close = rt_uart2_close; uart->read = rt_uart2_read; uart->write = rt_uart2_write; uart->control = RT_NULL; uart->user_data = RT_NULL; rt_device_register(uart, "uart2", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX); // find uart2 device G_Uart2Handle = rt_device_find("uart2"); if (G_Uart2Handle == RT_NULL) { rt_kprintf(" Packet_Tx_Thread err: can not find uart2"); return; } ret = rt_device_open(G_Uart2Handle, RT_DEVICE_OFLAG_RDWR); if(ret == RT_EOK) { // rt_kprintf(" uart2 open ok"); } else { rt_kprintf(" uart2 open Fail"); while(1) { rt_thread_delay(RT_TICK_PER_SECOND); } } } /* ********************************************************************************************************* * UART2私有函数 ********************************************************************************************************* */ /* * * 描述 : 写UART2设备 * * 参数 : rt_device_t dev,驱动的固定格式,暂不使用 * rt_off_t pos,驱动的固定格式,暂不使用 * const void* buffer,写入的数据的首地址 * rt_size_t size,希望写入的长度 * * 返回 : rt_size_t,实际写入的长度 * */ static rt_size_t rt_uart2_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) { uint16_t i = 0; uint16_t dma_tx_number; rt_uint8_t *ptr; rt_ubase_t level; rt_device_t uart = dev; ptr = (rt_uint8_t *)buffer; RT_ASSERT(uart != RT_NULL); level = rt_hw_interrupt_disable(); for(i = 0; i < size; i++) { // wait for one slot available in the SW Tx FIFO if (fifo_isFull(&f_uart2_txFifo)) { rt_kprintf(" uart2 txFifo full, discard"); break; } fifo_put(&f_uart2_txFifo, ptr[i]); // <- this is the only case of txFifo putting } rt_hw_interrupt_enable(level); // DMA通道空闲时,启动DMA通道 if(f_uart2_dma_tx_busy == RT_FALSE) { dma_tx_number = fifo_available(&f_uart2_txFifo); if(dma_tx_number > UART2_DMA_TXBUF_SIZE) { dma_tx_number = UART2_DMA_TXBUF_SIZE; } level = rt_hw_interrupt_disable(); for(i = 0; i < dma_tx_number; i++) { f_uart2_dma_txBuffer[i] = fifo_get(&f_uart2_txFifo); } rt_hw_interrupt_enable(level); #ifdef USART2_DMA_DEBUG rt_kprintf(" write%d",dma_tx_number); #endif uart2_DMA_tx_start(dma_tx_number); #ifdef USART2_DMA_DEBUG rt_kprintf(":%d",f_uart2_dma_tx_busy); #endif } return (rt_size_t) ptr - (rt_size_t) buffer; } /* * * 描述 : 读取UART2设备 * * 参数 : rt_device_t dev,驱动的固定格式,暂不使用 * rt_off_t pos,驱动的固定格式,暂不使用 * void* buffer,读取的数据存入的首地址 * rt_size_t size,希望读取的长度 * * 返回 : rt_size_t,实际读取的长度 * */ static rt_size_t rt_uart2_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) { rt_uint8_t* ptr; rt_device_t uart = dev; uint16_t i = 0; uint16_t buffer_used, read_number; RT_ASSERT(uart != RT_NULL); // point to buffer ptr = (rt_uint8_t*) buffer; buffer_used = uart2_available(); if(buffer_used >= size) { read_number = size; } else { read_number = buffer_used; } for(i = 0; i < read_number; i++) { ptr[i] = f_uart2_dma_rxBuffer[f_uart2_rxbuf_get_index]; f_uart2_rxbuf_get_index = (f_uart2_rxbuf_get_index + 1) % UART2_DMA_RXBUF_SIZE; } return (rt_uint32_t)ptr - (rt_uint32_t)buffer; } /* * * 描述 : 打开UART2设备 * * 参数 : rt_device_t dev,驱动的固定格式,暂不使用 * rt_uint16_t oflag,驱动的固定格式,暂不使用 * * 返回 : rt_err_t,固定RT_EOK * */ static rt_err_t rt_uart2_open(rt_device_t dev, rt_uint16_t oflag) { // enable DMA DMA_Cmd(UART2_TX_DMA_CHANNAL, ENABLE); DMA_Cmd(UART2_RX_DMA_CHANNAL, ENABLE); // enable USART USART_Cmd(USART2, ENABLE); USART_ClearFlag(USART2, USART_FLAG_TC); return RT_EOK; } /* * * 描述 : 关闭UART2设备 * * 参数 : rt_device_t dev,驱动的固定格式,暂不使用 * * 返回 : rt_err_t,固定RT_EOK * */ static rt_err_t rt_uart2_close(rt_device_t dev) { /* disable USART2 */ USART_Cmd(USART2, DISABLE); DMA_Cmd(UART2_TX_DMA_CHANNAL, DISABLE); DMA_Cmd(UART2_RX_DMA_CHANNAL, DISABLE); // clear software FIFOs fifo_clear(&f_uart2_txFifo); // 初始化缓冲区 rt_memset(&f_uart2_txBuffer, 0, sizeof(f_uart2_txBuffer)); // 初始化dma缓冲区 rt_memset(&f_uart2_dma_txBuffer, 0, sizeof(f_uart2_dma_txBuffer)); rt_memset(&f_uart2_dma_rxBuffer, 0, sizeof(f_uart2_dma_rxBuffer)); return RT_EOK; } /* * * 描述 : 初始化UART2硬件 * * 参数 : rt_device_t dev,驱动的固定格式,不使用 * * 返回 : rt_err_t,驱动的固定格式,RT_EOK * */ static rt_err_t rt_uart2_init (rt_device_t dev) { /* 1, Configure the GPIO ports */ uart2_GPIO_Configuration(); /* 2, NVIC configuration */ uart2_NVIC_Configuration(); /* 3, Configure the DMA */ uart2_DMA_Configuration(); /* 4, Configure the usart */ USART2_Configuration(); return RT_EOK; } /** * @brief Configures the DMA. * @param None * @retval None */ static void uart2_DMA_Configuration(void) { DMA_InitTypeDef DMA_InitStructure; /* DMA clock enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* USART2_Rx_DMA_Channel (triggered by USART2 Rx event) Config */ DMA_DeInit(UART2_RX_DMA_CHANNAL); DMA_InitStructure.DMA_PeripheralBaseAddr = USART2_BASE + 0x4; // USART_DR偏移量为0x4 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)f_uart2_dma_rxBuffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = UART2_DMA_RXBUF_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(UART2_RX_DMA_CHANNAL, &DMA_InitStructure); DMA_ITConfig(UART2_RX_DMA_CHANNAL, DMA_IT_TE, ENABLE); /* Enable USART2 DMA RX request */ USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE); // uart->open()时使能dma DMA_Cmd(UART2_RX_DMA_CHANNAL, DISABLE); /* DMA1 Channel7 (triggered by USART2 Tx event) Config */ DMA_DeInit(UART2_TX_DMA_CHANNAL); DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004404; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)f_uart2_dma_txBuffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = UART2_DMA_TXBUF_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(UART2_TX_DMA_CHANNAL, &DMA_InitStructure); DMA_ITConfig(UART2_TX_DMA_CHANNAL, DMA_IT_TC, ENABLE); DMA_ITConfig(UART2_TX_DMA_CHANNAL, DMA_IT_TE, ENABLE); /* Enable USART1 DMA TX request */ USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE); DMA_Cmd(UART2_TX_DMA_CHANNAL, DISABLE); } /** * @brief Configures the nested vectored interrupt controller. * @param None * @retval None */ static void uart2_NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* Enable the USART2 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //Enable DMA Channel7 Interrupt NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } static void USART2_Configuration(void) { USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, &USART_InitStructure); // 不使能USART2错误中断 // uart->open()时使能usart // USART_Cmd(USART2, ENABLE); // /* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去 // 如下语句解决第1个字节无法正确发送出去的问题 */ // USART_ClearFlag(USART2, USART_FLAG_TC); /* 清发送完成标志,Transmission Complete flag */ } static void uart2_DMA_tx_start(uint16_t tx_size) { USART_ClearFlag(USART2, USART_FLAG_TC); f_uart2_dma_tx_busy = RT_TRUE; // DMA传输开始标志量 DMA_Cmd(UART2_TX_DMA_CHANNAL, DISABLE); // 改变datasize前先要禁止通道工作 UART2_TX_DMA_CHANNAL->CNDTR = tx_size; // DMA1,传输数据量 DMA_Cmd(UART2_TX_DMA_CHANNAL, ENABLE); // 如果tx_size=1,将在下一句指令前进入dma中断 } /** * @brief Configures the different GPIO ports. * @param None * @retval None */ static void uart2_GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; /* 第1步:打开GPIO和USART2部件的时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); /* Enable the USART2 Pins Software Remapping */ GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE); /* 第2步:将USART2 Tx的GPIO配置为推挽复用模式 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); /* 第3步:将USART2 Rx的GPIO配置为浮空输入模式 由于CPU复位后,GPIO缺省都是浮空输入模式,因此下面这个步骤不是必须的 但是,我还是建议加上便于阅读,并且防止其它地方修改了这个口线的设置参数 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); } /* * * UART2接收中断回调函数 * * 描述 : 保留扩展用 * * 参数 : rt_device_t dev, uart2设备句柄 * 返回 : 错误状态 * */ static rt_err_t rt_uart2_rx_indicate(rt_device_t dev, rt_size_t size) { return RT_EOK; } /** * @brief This function handles USART2 global interrupt request. * @param None * @retval None */ void USART2_IRQHandler(void) { /* enter interrupt */ rt_interrupt_enter(); rt_kprintf(" Usart2 int"); // usrt2 Error interrupt if(USART_GetITStatus(USART2, USART_IT_ORE)) { rt_kprintf(",OverRun"); } if(USART_GetITStatus(USART2, USART_IT_NE)) { rt_kprintf(",Noise"); } if(USART_GetITStatus(USART2, USART_IT_FE)) { rt_kprintf(",Framing"); } if(USART_GetITStatus(USART2, USART_IT_PE)) { rt_kprintf(",Parity"); } // 清空错误中断标志 USART_ReceiveData(USART2); /* leave interrupt */ rt_interrupt_leave(); } // UART2_TX_DMA_CHANNAL void DMA1_Channel7_IRQHandler(void) { uint16_t dma_tx_number; uint16_t i = 0; rt_ubase_t level; /* enter interrupt */ rt_interrupt_enter(); DMA_Cmd(UART2_TX_DMA_CHANNAL, DISABLE);//关闭DMA #ifdef USART2_DMA_DEBUG rt_kprintf(" dma7"); #endif if(DMA_GetITStatus(DMA1_IT_TC7) == SET) { DMA_ClearITPendingBit(DMA1_IT_TC7); #ifdef USART2_DMA_DEBUG rt_kprintf(",TC"); #endif } if(DMA_GetITStatus(DMA1_IT_TE7) == SET) { DMA_ClearITPendingBit(DMA1_IT_TE7); #ifdef USART2_DMA_DEBUG rt_kprintf(",TE"); #endif } // 如果发送缓冲区非空,开启下次发送 dma_tx_number = fifo_available(&f_uart2_txFifo); if(dma_tx_number == 0) { // 如果发送缓冲区空,退出 f_uart2_dma_tx_busy = RT_FALSE; #ifdef USART2_DMA_DEBUG rt_kprintf(",%d",f_uart2_dma_tx_busy); #endif /* leave interrupt */ rt_interrupt_leave(); return; } else if(dma_tx_number > UART2_DMA_TXBUF_SIZE) { dma_tx_number = UART2_DMA_TXBUF_SIZE; } level = rt_hw_interrupt_disable(); for(i = 0; i < dma_tx_number; i++) { f_uart2_dma_txBuffer[i] = fifo_get(&f_uart2_txFifo); } rt_hw_interrupt_enable(level); uart2_DMA_tx_start(dma_tx_number); #ifdef USART2_DMA_DEBUG rt_kprintf("%d,%d",dma_tx_number, f_uart2_dma_tx_busy); #endif /* leave interrupt */ rt_interrupt_leave(); } // UART2_RX_DMA_CHANNAL void DMA1_Channel6_IRQHandler(void) { /* enter interrupt */ rt_interrupt_enter(); rt_kprintf(" dma1_6,"); // DMA 错误处理 if(DMA_GetITStatus(DMA1_FLAG_GL6)) { // DMA1 Channel7 transfer error flag. if(DMA_GetITStatus(DMA1_FLAG_TE6)) { DMA_ClearITPendingBit(DMA1_FLAG_TE6); rt_kprintf("uart2 dma rx err"); } // DMA1 Channel7 half transfer flag. if(DMA_GetITStatus(DMA1_FLAG_HT6)) { DMA_ClearITPendingBit(DMA1_FLAG_HT6); } // DMA1 Channel7 transfer complete flag if(DMA_GetITStatus(DMA1_FLAG_TC6)) { DMA_ClearITPendingBit(DMA1_FLAG_TC6); } DMA_ClearITPendingBit(DMA1_FLAG_GL6); } /* leave interrupt */ rt_interrupt_leave(); } /* * * 描述 : 返回uart2接收到的字节数 * * 参数 : 无 * * 返回 : uart2可用字节数 * */ rt_int32_t uart2_available(void) { uint16_t put_index, buffer_used; put_index = UART2_DMA_RXBUF_SIZE - DMA_GetCurrDataCounter(UART2_RX_DMA_CHANNAL); if(f_uart2_rxbuf_get_index <= put_index) { buffer_used = put_index - f_uart2_rxbuf_get_index; } else { buffer_used = UART2_DMA_RXBUF_SIZE + put_index - f_uart2_rxbuf_get_index; } return buffer_used; } /* * * 描述 : 返回uart2接收缓冲区第i个字节的内容,不修改缓冲区内容 * * 参数 : rt_uint16_t i * * 返回 : 第i个字节的内容 * */ rt_uint8_t uart2_rx_peek(rt_uint16_t i) { uint16_t read_index; if(i > uart2_available()) { return 0; } read_index = (f_uart2_rxbuf_get_index + i) % UART2_DMA_RXBUF_SIZE; return f_uart2_dma_rxBuffer[read_index]; } ```
虫少耶
2014-11-25
这家伙很懒,什么也没写!
二、usart2.h ``` /* * File : usart2.h * Change Logs: * Date Author Notes * 2014-6-19 zsf 第一版 */ #ifndef __UART2_H__ #define __UART2_H__ #define UART2_SW_FIFO_SIZE 300 #define UART2_DMA_TXBUF_SIZE 100 #define UART2_DMA_RXBUF_SIZE 400 #define UART2_BAUDRATE 115200 //DMA输出调试信息 // #define USART2_DMA_DEBUG // Uart2设备句柄,全局变量,程序使用Uart2必须通过这个句柄 extern rt_device_t G_Uart2Handle; extern void uart2_entry(void* parameter); extern void rt_hw_uart2_init(void); extern rt_err_t IsUart2Initialized(void); extern rt_int32_t uart2_available(void); extern rt_uint8_t uart2_rx_peek(rt_uint16_t i); extern void UART2_IRQHandler(void); extern void DMA1_Channel7_IRQHandler(void); extern void DMA1_Channel6_IRQHandler(void); #endif ```
虫少耶
2014-11-25
这家伙很懒,什么也没写!
三、fifo.c是我以前的项目里用到的,是从网上找来修改得到的,向原作者致敬。 ``` /************************************************************************ Copyright (c) 2011, Nic McDonald All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ************************************************************************* Information: File Name : fifo.c Author(s) : Nic McDonald Hardware : Any Purpose : First In First Out Buffer ************************************************************************* Modification History: Revision Date Author Description of Revision 1.00 05/30/2011 NGM initial ************************************************************************* Theory of Operation: This FIFO implementation provides a memory safe 'First In First Out' circular buffer. If the operating conditions of a FIFO causes it to 'underflow' or 'overflow' the FIFO will not corrupt memory other than its own data buffer. However, memory accesses into the buffer will be invalid. If a FIFO 'underflows' or 'overflows', it should be re-initialized or cleared. Example Usage: volatile uint8_t fifo_buf[128]; FIFO fifo; fifo_init(&fifo, 128, fifo_buf); ************************************************************************/ #include "fifo.h" #include
void fifo_init(FIFO* f, uint32_t size, uint8_t* data) { f->size = size; f->data = data; f->status = FIFO_GOOD; f->putIndex = 0; f->getIndex = 0; f->used = 0; } uint32_t fifo_isFull(FIFO* f) { return (f->used >= f->size); } uint32_t fifo_isEmpty(FIFO* f) { return (f->used == 0); } uint8_t fifo_get(FIFO* f) { uint8_t c; if (f->used > 0) { c = f->data[f->getIndex]; f->data[f->getIndex] = 0; // 2014-6-25 f->getIndex = (f->getIndex+1) % f->size; f->used--; f->status = FIFO_GOOD; return c; } else { f->status = FIFO_UNDERFLOW; return 0; } } void fifo_put(FIFO* f, uint8_t c) { if (f->used >= f->size) { f->status = FIFO_OVERFLOW; } else { f->data[f->putIndex] = c; f->putIndex = (f->putIndex+1) % f->size; f->used++; f->status = FIFO_GOOD; } } /* uint8_t fifo_peek(FIFO* f) { return f->data[f->getIndex]; } */ //返回fifo内字节数量 uint32_t fifo_available(FIFO* f) { return f->used; } void fifo_clear(FIFO* f) { f->status = FIFO_GOOD; f->putIndex = 0; f->getIndex = 0; f->used = 0; } uint8_t fifo_status(FIFO* f) { return f->status; } /* ********************************************************************************************************* * 从fifo读取1字节 * *描述 : 读取fifo中的第i个有效数据,但不修改fifo * *参数 : rt_uint8_t i,指定fifo中的第i个有效数据,从0开始计算 * FIFO* f,fifo指针 * *返回 : 有效数据,如果fifo的数据>=i * 0,如果接收到的数据
f->used) //2013-8-13修改i为(i + 1) { f->status = FIFO_UNDERFLOW; return 0; //如果fifo数据少于i,返回0 } Offset = (f->getIndex + i) % f->size; c = f->data[Offset]; f->status = FIFO_GOOD; return c; } void check_fifo_status(FIFO* f, const char * s) { if(f->status == FIFO_GOOD) { return; } else { rt_kprintf(s); switch(f->status) { case FIFO_OVERFLOW: rt_kprintf("FIFO_OVERFLOW"); break; case FIFO_UNDERFLOW: rt_kprintf("FIFO_UNDERFLOW"); break; default: rt_kprintf("unknown(%x)", f->status); break; } } } ```
虫少耶
2014-11-25
这家伙很懒,什么也没写!
四、fifo.h ``` /************************************************************************ Copyright (c) 2011, Nic McDonald All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ************************************************************************* Information: File Name : fifo.h Author(s) : Nic McDonald Hardware : Any Purpose : First In First Out Buffer ************************************************************************* Modification History: Revision Date Author Description of Revision 1.00 05/30/2011 NGM initial ************************************************************************/ #ifndef _FIFO_H_ #define _FIFO_H_ /* includes */ #include
#include "rtdef.h" /* defines */ #define FIFO_GOOD 0x00 #define FIFO_OVERFLOW 0x01 #define FIFO_UNDERFLOW 0x02 /* typedefs */ typedef struct { volatile uint32_t size; volatile uint8_t* data; volatile uint8_t status; volatile uint32_t putIndex; volatile uint32_t getIndex; volatile uint32_t used; } FIFO; /* functions */ void fifo_init(FIFO* f, uint32_t size, uint8_t* data); uint32_t fifo_isFull(FIFO* f); uint32_t fifo_isEmpty(FIFO* f); uint8_t fifo_get(FIFO* f); void fifo_put(FIFO* f, uint8_t c); // uint8_t fifo_peek(FIFO* f); extern uint32_t fifo_available(FIFO* f); void fifo_clear(FIFO* f); uint8_t fifo_status(FIFO* f); extern rt_uint8_t fifo_peek(rt_uint32_t i, FIFO* f); extern void check_fifo_status(FIFO* f, const char * s); #endif // _FIFO_H_ ```
虫少耶
2014-11-25
这家伙很懒,什么也没写!
五、spi.c ``` /* * File : spi.c * * Change Logs: * Date Author Notes * 2014-10-8 zsf The first version for stm32f107 * */ #include "stm32f10x.h" #include "spi.h" #include
#include
#define SPI1_CLK RCC_APB2Periph_SPI1 #define SPI1_GPIO GPIOA #define SPI1_GPIO_CLK RCC_APB2Periph_GPIOA #define SPI1_PIN_SCK GPIO_Pin_5 #define SPI1_PIN_MISO GPIO_Pin_6 #define SPI1_PIN_MOSI GPIO_Pin_7 #define SPI1_PIN_CS GPIO_Pin_4 #define Dummy_Byte 0xA5 /********************************************************************************************************** * SPI1私有变量 **********************************************************************************************************/ struct rt_device spi1_device; /********************************************************************************************************** * SPI1声明 **********************************************************************************************************/ void spi1_RCC_Configuration(void); void spi1_GPIO_Configuration(uint16_t SPI_Mode); void spi1_Configuration(void); void spi1_cs_disable(void); /********************************************************************************************************** * SPI1私有函数 **********************************************************************************************************/ static rt_err_t rt_spi1_init (rt_device_t dev) { spi1_RCC_Configuration(); spi1_GPIO_Configuration(SPI_Mode_Master); spi1_Configuration(); return RT_EOK; } void spi1_Configuration(void) { SPI_InitTypeDef SPI_InitStructure; /* SPI1初始化配置*/ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // CPOL=1,时钟空闲时为高 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // 第二个沿,上升沿有效 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // SPI分频值,分频后的值为SCK的时钟频率 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // MSB First SPI_InitStructure.SPI_CRCPolynomial = 7; // 与CRC校验有关 SPI_Init(SPI1, &SPI_InitStructure); } /** * @brief Configures the different SPI1 GPIO ports. * @param SPI_Mode: Specifies the SPIy operating mode. * This parameter can be: * - SPIy_Mode_Master * - SPIy_Mode_Slave * @retval None */ void spi1_GPIO_Configuration(uint16_t SPI_Mode) { GPIO_InitTypeDef GPIO_InitStructure; /*!初始化时钟信号线SCK,MOSI */ GPIO_InitStructure.GPIO_Pin = SPI1_PIN_SCK | SPI1_PIN_MOSI; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; if(SPI_Mode == SPI_Mode_Master) { /* Configure SCK and MOSI pins as Alternate Function Push Pull */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; } else { /* Configure SCK and MOSI pins as Input Floating */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; } GPIO_Init(SPI1_GPIO, &GPIO_InitStructure); /*初始化SPI_FLASH_SPI管脚: MISO */ GPIO_InitStructure.GPIO_Pin = SPI1_PIN_MISO; if(SPI_Mode == SPI_Mode_Master) { /* Configure MISO pin as Input Floating */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; } else { /* Configure MISO pin as Alternate Function Push Pull */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; } GPIO_Init(SPI1_GPIO, &GPIO_InitStructure); /*初始化片选信号管脚: /CS*/ GPIO_InitStructure.GPIO_Pin = SPI1_PIN_CS; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(SPI1_GPIO, &GPIO_InitStructure); spi1_cs_disable(); } /** * @brief Configures the different system clocks. * @param None * @retval None */ void spi1_RCC_Configuration(void) { /* Enable GPIO clock for SPI1*/ /* Enable SPI1 Periph clock */ RCC_APB2PeriphClockCmd(SPI1_GPIO_CLK | SPI1_CLK, ENABLE); } void spi1_cs_enable(void) { GPIO_ResetBits(SPI1_GPIO, SPI1_PIN_CS); //片选引脚/CS拉低 } void spi1_cs_disable(void) { GPIO_SetBits(SPI1_GPIO, SPI1_PIN_CS); //片选引脚/CS拉高 } static rt_err_t rt_spi1_open(rt_device_t dev, rt_uint16_t oflag) { RT_ASSERT(dev != RT_NULL); /*使能SPI1 */ SPI_Cmd(SPI1, ENABLE); return RT_EOK; } static rt_err_t rt_spi1_close(rt_device_t dev) { RT_ASSERT(dev != RT_NULL); /*关闭SPI1 */ SPI_Cmd(SPI1, DISABLE); return RT_EOK; } /** * @函数名 spi1_send_byte * @功能 通过SPI1总线发送一个字节数据(顺便接收一个字节数据) * Sends a byte through the SPI interface and return the byte * received from the SPI bus. * @参数 要写入的一个字节数据 * @返回值 在发数据时,MISO信号线上接收的一个字节 ***/ uint8_t spi1_send_byte(uint8_t byte) { /* Loop while DR register in not emplty */ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); /* Send byte through the SPI1 peripheral */ SPI_I2S_SendData(SPI1, byte); /* Wait to receive a byte */ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); /* Return the byte read from the SPI bus */ return SPI_I2S_ReceiveData(SPI1); } /** * @函数名 spi1_read_byte * @功能 读取SPI1的一个字节,未包含发送读命令和起始地址 * @参数 无 * @返回值 从SPI1读取的一个字节 ***/ uint8_t spi1_read_byte(void) { return (spi1_send_byte(Dummy_Byte)); } static rt_size_t rt_spi1_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) { rt_uint8_t* ptr; rt_device_t spi = dev; RT_ASSERT(spi != RT_NULL); // point to buffer ptr = (rt_uint8_t*) buffer; spi1_cs_enable(); while(size) { *ptr = spi1_read_byte(); ptr ++; size --; } spi1_cs_disable(); return (rt_uint32_t)ptr - (rt_uint32_t)buffer; } static rt_size_t rt_spi1_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) { rt_uint8_t *ptr; rt_device_t spi = dev; ptr = (rt_uint8_t *)buffer; RT_ASSERT(spi != RT_NULL); spi1_cs_enable(); while(size) { spi1_send_byte(*ptr); ptr++; size--; } spi1_cs_disable(); return (rt_size_t) ptr - (rt_size_t) buffer; } void rt_hw_spi1_init(void) { rt_device_t spi; // get spi device spi = &spi1_device; // device initialization spi->type = RT_Device_Class_SPIDevice; // device interface spi->init = rt_spi1_init; spi->open = rt_spi1_open; spi->close = rt_spi1_close; spi->read = rt_spi1_read; spi->write = rt_spi1_write; spi->control = RT_NULL; spi->user_data = RT_NULL; rt_device_register(spi, "spi1", RT_DEVICE_FLAG_RDWR); } ```
虫少耶
2014-11-25
这家伙很懒,什么也没写!
六、spi.h ``` #ifndef __SPI_H__ #define __SPI_H__ extern void rt_hw_spi1_init(void); #endif ```
撰写答案
登录
注册新账号
关注者
0
被浏览
7.8k
关于作者
虫少耶
这家伙很懒,什么也没写!
提问
5
回答
14
被采纳
0
关注TA
发私信
相关问题
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
【NXP-MCXA153】 定时器驱动移植
2
GD32F450 看门狗驱动适配
3
【NXP-MCXA153】看门狗驱动移植
4
RT-Thread Studio V2.2.9 Release Note
5
CherryUSB的bootuf2配置
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
freemodbus
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
7
个答案
2
次被采纳
a1012112796
15
个答案
1
次被采纳
Ryan_CW
5
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
本月文章贡献
YZRD
3
篇文章
6
次点赞
catcatbing
3
篇文章
6
次点赞
lizimu
2
篇文章
8
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部