我就说个 简单的 吧 比如 定义 int i ; 那我们 给数据 给 i 时候 是i=10; 你说 i 是 他的 地址吗 显然 不是 然后 我要得到他的 地址 就是在 i 前面加个 &I 就是 他的 地址 了 , 我感觉 这样 你会 好理解点 还有 那个 第一个 赋值 里面的& 是 与运算 表示 只取data 数据中的低九位 好了 就到这 希望 你能明白 吧DMA接收数据只采用查询用此函数还可以。
但同时开了DMA中断的~~~~~~~
不管什么时候,都是接收完整个数据包之后才对该包进行处理,是吧?
函数DMA_GetCurrDataCounte()只得到当前收到了多少个数据,而不知道接收数据完成没有的
STM32要是有串口接收超时功能就好了。
问:如何利用STM32的资源自己做个类似超时的功能?加上DMA作为类似的接收FIFOint main( void )
{
//
//
系统初始化
//
system_init( );
//
时钟初始化
drv_rcc_init( 0, 0, 64, APB1_PRESC_2, APB2_PRESC_1, 0x08000000 );
hal_timer_init( 5000 );
//TIM1
配置为
编码器模式
DMA
触发请求为外部其他定时的触发输出
//TIM4
配置为触发输出
用于定时器给一个触发信号到
TIM1
//
输入通道引脚初始化
drv_rcc_ahb1_clk_enable( RCC_AHBENR_GPIOEEN );
drv_gpio_alternate_function_init( GPIOE, GPIO_PIN_9, GPIO_PUPD_PULL, GPIO_OTYPE_OD,
GPIO_SPEED_MID );
drv_gpio_alternate_function_init(
GPIOE,
GPIO_PIN_11,
GPIO_PUPD_PULL,
GPIO_OTYPE_OD, GPIO_SPEED_MID );
drv_gpio_alternate_function_connect( GPIOE, GPIO_PINSOURCE9, GPIO_AF2_TIM1 );
drv_gpio_alternate_function_connect( GPIOE, GPIO_PINSOURCE11, GPIO_AF2_TIM1 );
//TIM1
初始化
drv_rcc_apb2_clk_enable( RCC_APB2ENR_TIM1EN );
drv_timer_base_init( TIM1, 0, 0xFFFF, TIM_EDGE_CNT_MODE_UP );
drv_timer_select_input_trigger( TIM1, TIM_TS_ITR3 );
drv_timer_select_slave_mode( TIM1, TIM_SLAVE_MODE_EQEP_3 );
//
TIM_SLAVE_MODE_TRIGGER
//
输入通道配置
drv_timer_ic1_init(
TIM1,
TIM_IC_POLARITY_RISING,
TIM_IC_PSC_DIV_1,
TIM_IC_SELECTION_1, Filter_NO );
drv_timer_ic2_init(
TIM1,
TIM_IC_POLARITY_RISING,
TIM_IC_PSC_DIV_1,
TIM_IC_SELECTION_1, Filter_NO );
drv_timer_ic1_enable( TIM1 );
drv_timer_ic2_enable( TIM1 );
//TIM
定时器配置
TIM1->DIERbitTDE = 1;
//
使能触发
DMA
请求
TIM1->DCRbitDBL = 0;
//
传输个数
TIM1->DCRbitDBA = 9;
//
基地址为
TIM1->CNT
//TIM1 DMA
初始化
DMA1 CHANNEL4 :TIM1_TRIG
drv_rcc_ahb1_clk_enable( RCC_AHBENR_DMA1EN );
drv_dma_stream_deinit( DMA1_Channel4 );
drv_dma_stream_init(
DMA1_Channel4,
(UINT32)g_TimerCntBuffer,
UINT32)(&( TIM1->CNT )), 5, DMA_CIRC_MODE_ENABLE,
DMA_CHANNEL_PRIORITY_VERY_HIGH,
DMA_DIR_PERIPH_TO_MEM, DMA_DATA_WIDTH_WORD );
drv_dma_stream_enable( DMA1_Channel4 );
//TIM4
初始化
drv_rcc_apb1_clk_enable( RCC_APB1ENR_TIM4EN );
drv_timer_base_init( TIM4, 1000000, 5000, TIM_EDGE_CNT_MODE_UP );
drv_timer_select_output_trigger( TIM4, TIM_TRGOSource_Update );
//
根
新
事
件
作
为
触发输出
drv_timer_enable( TIM1 );
drv_timer_enable( TIM4 );
while( 1 )
{
//
hal_watchdog_feed( );
}
}查询就是一直在查看标志位,是不是被置1了,如果是就去读或者其他 *** 作
中断就是平时不用管,一单有东西来就会进入中断服务程序,你再去 *** 作
DMA是你初始化的时候把串口地址和需要传输的地址写上,来东西他就自己把数据存到你初始化的地址上,可以连续,或者传输完中断,丫的,不采纳我真是对不起我。都是手打的其中TI1为CPU引脚的输入,经过滤波(新的电平必须保持一定时间才认为有效,以防止高频噪声的干扰)後进入後继的边沿极性选择,最後经过分频作为捕获信号的输入。这里TI2F为相邻通道经过滤波後的信号,也就是说一个引脚的信号可作为TIMx两个通道的输入捕获信号,这样信号只需要接一个CPU引脚就可以触发两个时钟通道了。
将输入方波接到CPU一个引脚上,假设该引脚对应於图上的TI1,设定其在下降沿触发通道1的捕获事件,而其在上升沿触发通道2的捕获事件,事件发生後申请DMA将捕获的比较/捕获寄存器的值保存起来。示例代码如下:

其他部分与第3节中比较输出的代码基本一致。
5 总结
测试中STM32系列微控制器工作在36MHz,可产生出1路最高1.5MHz的方波,可捕获1MHz的方波,而此时CPU的执行几乎不受影响。这里采用DMA来实现方波的产生和捕获,极大地提高了系统的实时性和执行效率,减少了中断次数,节省了宝贵的资源。这种方案也可以用来实现高效的模拟串口。
DMA的传输需要多个系统周期的,例如采用DMA实现内存到内存的搬移,每次传输需要5个系统周期,而内存到外围的一次传输需要2个APB周期+5个AHB周期。这样用上述方法产生的方波最小沿(低沿或高沿)为14个周期(包括比较/捕获寄存器到内部影子寄存器的传输等)。若有更高的需求,应考虑其他的实现方案。另外,若有多个DMA同时工作,应考虑最坏情况下DMA的响应时间,以避免错误发生。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)