目录
一.DMA
1.概念
2.DMA的特征
?3.DMA的工作方式
二.高低电平控制控制LED灯亮和灭
三.中断实现串口通信
四.总结
五.参考文献
一.DMA
1.概念
“Direct Memory Access(存储器直接访问)。这是指一种高速的数据传输操作,允许在外部设备和存储器之间直接读写数据。整个数据传输操作在一个称为"DMA控制器"的控制下进行的。CPU除了在数据传输开始和结束时做一点处理外(开始和结束时候要做中断处理),在传输过程中CPU可以进行其他的工作(前提是未设置停止CPU访问)。这样,在大部分时间里,CPU和输入输出都处于并行操作。因此,使整个计算机系统的效率大大提高”。?
DMA传送方式是让存储器与外设、或外设与外设之间直接交换数据,不需要经过CPU的累加器中转,减少了这个中间环节,并且内存地址的修改、传送完毕的结束报告都是由硬件电路实现的,因此大大地提高了数据的传输速度。一个DMA传送只需要执行一个DMA周期,相当于一个总线读写周期。DMA是在专门的硬件( DMA)控制下,实现高速外设和主存储器之间自动成批交换数据尽量减少CPU干预的输入/输出操作方式。?
2.DMA的特征
每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置;
在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推); 独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐; 支持循环的缓冲器管理; 每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求; 存储器和存储器间的传输、外设和存储器、存储器和外设之间的传输; 闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标; 可编程的数据传输数目:最大为65535 ?
?3.DMA的工作方式
DMA的工作方式 (因为DMA和CPU都要使用总线,工作方式的区分也就是基于总线的分配方式)
1,停止CPU访内
总线全部给DMA使用。
2,周启挪用方式
周期挪用,又叫周期窃取,是指利用CPU不访问存储器的那些周期来实现DMA操作,此时DMA可以使用总线而不用通知CPU也不会妨碍CPU的工作。周期挪用并不减慢CPU的操作,但可能需要复杂的时序电路,而且数据传输过程是不连续的和不规则的。
(周期窃取,是DMA方式中由DMA接口向CPU申请占用总线,占用一个存取周期。)
与CPU暂停访存的方式相比,它既实现了I/O传送,又较好地发挥了主存与CPU的效率,是一种广泛采用的方法。应该指出,I/O设备每挪用一个主存周期都要申请总线控制权、建立总线控制权和归还总线控制级权。因此,尽管传送一个字对主存而言只占用一个主存周期,但对DMA接口而言,实质上要占2—5个主存周期(由逻辑线路的延迟特性而定)。因此周期挪用的方法比较适合于I/O设备的读写周期大于主存周期的情况。
3,DMA与CPU交替访内 ?
二.高低电平控制控制LED灯亮和灭
1.进入STMCUBEX,选择新建项目
?2.搜索F103C8,点击右侧的选项,创建新的项目
?点击sys,将debug选项改为Serial Wire
然后在Rcc里的HSE选择Crystal/Ceramic Resonator
?
?将PB0选为外部中断触发器,PA1是控制led灯的,和将它选择为GPIO_output就行了
?
选择PLLCLK,然后将后面的晶振频率最大值改为72M赫兹
?
project里把toolchain那里改为MDK-ARM,版本选择最新的就行了,项目名和项目路径自己选择
?
?选择生成初始化文件,然后选择生成代码就好了
?开项目,来到keil5,进入到mian.c里,接下来就是刚刚提到的在回调函数里写代码了,将回调函数重写一遍就行了,代码如下
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
GPIO_PinState b0_pin = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0); // 读取b0的状态
b0_pin=1-b0_pin;
switch (GPIO_Pin){//判断引脚
case GPIO_PIN_0:
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1,1-b0_pin); // 将a1写入与b0相同的电位
break;
}
}
三.中断实现串口通信
1.新建项目
?
?选择UASRT1,将mode改为异步通信,选择下面的NVIC Setting,将enabled选上
?
选择UASRT1,将mode改为异步通信,选择下面的NVIC Setting,将enabled选上
?
- 然后将HAL_UART_RxCpltCallback函数重写,和上面的回调函数是一个道理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(Uart1_Rx_Cnt >= 255) //溢出判断
{
Uart1_Rx_Cnt = 0;
memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff));
HAL_UART_Transmit(&huart1, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);
}
else
{
Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer; //接收数据转存
if((Uart1_RxBuff[Uart1_Rx_Cnt-1] == 0x0A)||(Uart1_RxBuff[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
{
HAL_UART_Transmit(&huart1, (uint8_t *)&Uart1_RxBuff, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
Uart1_Rx_Cnt = 0;
memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff)); //清空数组
}
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); //再开启接收中断
}
四.总结
学习DMA与说stm32知识深化了学习深度。
五.参考文献
【STM32CubeMX】HAL库中断方式UART串口通信 STM32之中断控制LED灯
DMA总结_wuyongpeng的专栏-CSDN博客_dma
|