关于IDE DMA的简单说明.

本文详细介绍了标准编程序列,用于启动 IDE DMA 设备与内存之间的总线主机数据传输过程。主要包括准备 PRD 表、设置 PRD 表指针寄存器、发送 DMA 命令、启动总线主机功能、响应数据传输请求、处理传输结束中断等步骤。
部署运行你感兴趣的模型镜像
3.1. Standard Programming Sequence
To initiate a bus master transfer between memory and an IDE DMA slave device, the following steps are
required:
1) Software prepares a PRD Table in system memory. Each PRD is 8 bytes long and consists of an
address pointer to the starting address and the transfer count of the memory buffer to be
transferred. In any given PRD Table, two consecutive PRDs are offset by 8-bytes and are aligned
on a 4-byte boundary.
2) Software provides the starting address of the PRD Table by loading the PRD Table Pointer
Register . The direction of the data transfer is specified by setting the Read/Write Control bit.
Clear the Interrupt bit and Error bit in the Status register.
3) Software issues the appropriate DMA transfer command to the disk device.
4) Engage the bus master function by writing a '1' to the Start bit in the Bus Master IDE Command
Register for the appropriate channel.
5) The controller transfers data to/from memory responding to DMA requests from the IDE device.
6) At the end of the transfer the IDE device signals an interrupt.
7) In response to the interrupt, software resets the Start/Stop bit in the command register. It then
reads the controller status and then the drive status to determine if the transfer completed
successfully.

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

检查是否有误#include "stm32f10x.h" #include <math.h> #define WAVE_TABLE_SIZE 256 #define PI 3.14159265358979323846 // 全局变量 uint16_t sine_wave[WAVE_TABLE_SIZE]; uint16_t triangle_wave[WAVE_TABLE_SIZE]; uint16_t square_wave[WAVE_TABLE_SIZE]; uint16_t *current_wave = sine_wave; uint32_t frequency_level = 100; // 改为 uint32_t,支持更大范围 uint16_t amplitude = 2048; // 幅度:0 ~ 4095 // 函数声明 void RCC_Configuration(void); void GPIO_Configuration(void); void DAC_Configuration(void); void TIM2_Configuration(void); void DMA_Configuration(void); void WAVE_GenerateTables(void); int Read_Key(int key_num); void Update_DMA_Address(uint16_t* new_addr); void delay_ms(uint32_t ms); int main(void) { SystemInit(); // 初始化系统时钟(默认 72MHz) RCC_Configuration(); GPIO_Configuration(); WAVE_GenerateTables(); // 生成初始波形表 DAC_Configuration(); DMA_Configuration(); TIM2_Configuration(); TIM_Cmd(TIM2, ENABLE); // 启动定时器,开始触发 DAC 输出 while (1) { // 按键处理(带消抖) if (Read_Key(0) == 0) { // PA15: 切换波形 delay_ms(20); while (Read_Key(0) == 0); // 等待释放 if (current_wave == sine_wave) current_wave = triangle_wave; else if (current_wave == triangle_wave) current_wave = square_wave; else current_wave = sine_wave; Update_DMA_Address(current_wave); } if (Read_Key(1) == 0) { // PB4: 增加频率 delay_ms(20); while (Read_Key(1) == 0); if (frequency_level > 10) frequency_level -= 5; TIM2->ARR = frequency_level; } if (Read_Key(2) == 0) { // PB5: 降低频率 delay_ms(20); while (Read_Key(2) == 0); if (frequency_level < 65000) frequency_level += 5; TIM2->ARR = frequency_level; } if (Read_Key(3) == 0) { // PB6: 增大幅度 delay_ms(20); while (Read_Key(3) == 0); if (amplitude < 4000) amplitude += 256; WAVE_GenerateTables(); Update_DMA_Address(current_wave); } if (Read_Key(4) == 0) { // PB7: 减小幅度 delay_ms(20); while (Read_Key(4) == 0); if (amplitude > 256) amplitude -= 256; WAVE_GenerateTables(); Update_DMA_Address(current_wave); } } } // 生成三种波形查找表(根据当前 amplitude 缩放) void WAVE_GenerateTables(void) { for (int i = 0; i < WAVE_TABLE_SIZE; i++) { // 正弦波:sin(x) ∈ [-1,1] → 映射到 [0, amplitude] float angle = 2 * PI * i / WAVE_TABLE_SIZE; sine_wave[i] = (uint16_t)((sin(angle) * 0.5 + 0.5) * amplitude); // 三角波:上升一半,下降一半 if (i < WAVE_TABLE_SIZE / 2) triangle_wave[i] = (uint16_t)((2.0 * i / WAVE_TABLE_SIZE) * amplitude); else triangle_wave[i] = (uint16_t)((2.0 * (WAVE_TABLE_SIZE - i)) / WAVE_TABLE_SIZE * amplitude); // 方波:前半高,后半低 square_wave[i] = (i < WAVE_TABLE_SIZE / 2) ? amplitude : 0; } } // RCC时钟使能 void RCC_Configuration(void) { // 使能各外设时钟 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd( RCC_APB1Periph_DAC | RCC_APB1Periph_TIM2, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); } // GPIO配置 void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; // PA4: DAC OUT1 (模拟输出) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入模式(DAC专用) GPIO_Init(GPIOA, &GPIO_InitStructure); // PA15: 按键1(切换波形) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入 GPIO_Init(GPIOA, &GPIO_InitStructure); // PB4~PB7: 按键2~5 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB, &GPIO_InitStructure); } // DAC配置(通道1,由TIM2触发,DMA传输) void DAC_Configuration(void) { DAC_InitTypeDef DAC_InitStructure; DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO; // 触发源:TIM2更新事件 DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = 0; DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; DAC_Init(DAC_Channel_1, &DAC_InitStructure); DAC_Cmd(DAC_Channel_1, ENABLE); DAC_DMACmd(DAC_Channel_1, ENABLE); // 使能DAC的DMA请求 } // DMA配置:将波形数组传送到DAC寄存器 void DMA_Configuration(void) { DMA_InitTypeDef DMA_InitStructure; DMA_DeInit(DMA1_Channel3); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(DAC->DHR12R1); // DAC数据寄存器地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)current_wave; // 当前波形表起始地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = WAVE_TABLE_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = ENABLE; DMA_InitStructure.DMA_PeripheralDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel3, &DMA_InitStructure); DMA_Cmd(DMA1_Channel3, ENABLE); } // 更新DMA内存地址(安全方式:重新初始化DMA通道) void Update_DMA_Address(uint16_t* new_addr) { DMA_Cmd(DMA1_Channel3, DISABLE); DMA_DeInit(DMA1_Channel3); DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(DAC->DHR12R1); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)new_addr; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = WAVE_TABLE_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = ENABLE; DMA_InitStructure.DMA_PeripheralDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel3, &DMA_InitStructure); DMA_Cmd(DMA1_Channel3, ENABLE); } // TIM2配置:提供周期性触发信号给DAC void TIM2_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period = frequency_level; // 自动重载值 TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // 72MHz / 72 = 1MHz 计数频率 TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // 设置TRGO信号为更新事件(Update Event) TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); } // 读取按键状态:key_num=0~4 对应 PA15,PB4~PB7 int Read_Key(int key_num) { static const uint16_t pins[5] = { GPIO_Pin_15, // PA15 GPIO_Pin_4, // PB4 GPIO_Pin_5, // PB5 GPIO_Pin_6, // PB6 GPIO_Pin_7 // PB7 }; static const GPIO_TypeDef* ports[5] = { GPIOA, GPIOB, GPIOB, GPIOB, GPIOB }; return GPIO_ReadInputDataBit((GPIO_TypeDef*)ports[key_num], pins[key_num]); } // 简易毫秒延时函数(忙等待) void delay_ms(uint32_t ms) { volatile uint32_t nCount; while (ms--) { nCount = 72000; // 约1ms @72MHz while (nCount--) { __NOP(); } } }
12-19
#include "stm32f10x.h" #include <math.h> #include <stdint.h> // 提供 uint16_t, uint32_t #define WAVE_TABLE_SIZE 256 #define PI 3.14159265358979323846 // 全局变量 uint16_t sine_wave[WAVE_TABLE_SIZE]; uint16_t triangle_wave[WAVE_TABLE_SIZE]; uint16_t square_wave[WAVE_TABLE_SIZE]; uint16_t *current_wave = sine_wave; uint32_t frequency_level = 100; // 定时器自动重载值(影响频率) uint16_t amplitude = 2048; // 幅度:0 ~ 4095 // 函数声明 void RCC_Configuration(void); void GPIO_Configuration(void); void DAC_Configuration(void); void TIM2_Configuration(void); void DMA_Configuration(void); void WAVE_GenerateTables(void); int Read_Key(int key_num); void Update_DMA_Address(uint16_t* new_addr); void delay_ms(uint32_t ms); /** * 主函数 */ int main(void) { SystemInit(); // 初始化系统时钟(默认 72MHz) RCC_Configuration(); GPIO_Configuration(); WAVE_GenerateTables(); // 生成初始波形表 DAC_Configuration(); DMA_Configuration(); TIM2_Configuration(); TIM_Cmd(TIM2, ENABLE); // 启动定时器,开始触发 DAC 输出 while (1) { // 按键处理(带消抖) // PA15: 切换波形 if (Read_Key(0) == 0) { delay_ms(20); while (Read_Key(0) == 0); // 等待按键释放 if (current_wave == sine_wave) current_wave = triangle_wave; else if (current_wave == triangle_wave) current_wave = square_wave; else current_wave = sine_wave; Update_DMA_Address(current_wave); } // PB4: 增加频率(减小 ARR) if (Read_Key(1) == 0) { delay_ms(20); while (Read_Key(1) == 0); if (frequency_level > 10) frequency_level -= 5; TIM2->ARR = frequency_level; // ✅ 直接修改自动重载寄存器 } // PB5: 降低频率(增大 ARR) if (Read_Key(2) == 0) { delay_ms(20); while (Read_Key(2) == 0); if (frequency_level < 65000) frequency_level += 5; TIM2->ARR = frequency_level; // ✅ 直接修改 } // PB6: 增大幅度 if (Read_Key(3) == 0) { delay_ms(20); while (Read_Key(3) == 0); if (amplitude < 4000) amplitude += 256; WAVE_GenerateTables(); Update_DMA_Address(current_wave); } // PB7: 减小幅度 if (Read_Key(4) == 0) { delay_ms(20); while (Read_Key(4) == 0); if (amplitude > 256) amplitude -= 256; WAVE_GenerateTables(); Update_DMA_Address(current_wave); } } } /** * 生成三种波形查找表 */ void WAVE_GenerateTables(void) { for (int i = 0; i < WAVE_TABLE_SIZE; i++) { float angle = 2.0f * PI * i / WAVE_TABLE_SIZE; // 正弦波:偏移至 0~1 范围 sine_wave[i] = (uint16_t)((sin(angle) * 0.5f + 0.5f) * amplitude); // 三角波:上升一半,下降一半 if (i < WAVE_TABLE_SIZE / 2) triangle_wave[i] = (uint16_t)((2.0f * i / WAVE_TABLE_SIZE) * amplitude); else triangle_wave[i] = (uint16_t)((2.0f * (WAVE_TABLE_SIZE - i)) / WAVE_TABLE_SIZE * amplitude); // 方波:前半周期高,后半周期低 square_wave[i] = (i < WAVE_TABLE_SIZE / 2) ? amplitude : 0; } } /** * RCC 时钟使能配置 */ void RCC_Configuration(void) { RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd( RCC_APB1Periph_DAC | RCC_APB1Periph_TIM2, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); } /** * GPIO 配置 */ void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; // PA4: DAC OUT1 (模拟输出) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入模式 GPIO_Init(GPIOA, &GPIO_InitStructure); // PA15: 按键输入(切换波形),上拉 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &GPIO_InitStructure); // PB4~PB7: 按键输入(频率/幅度控制),共用上拉 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB, &GPIO_InitStructure); } /** * DAC 配置 */ void DAC_Configuration(void) { DAC_InitTypeDef DAC_InitStructure; DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO; // 由 TIM2 TRGO 触发 DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; // 不使用内置波形 DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; // 外部驱动能力强可关闭缓冲 DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; // 占位符,不影响 DAC_Init(DAC_Channel_1, &DAC_InitStructure); DAC_Cmd(DAC_Channel_1, ENABLE); // 使能通道1 DAC_DMACmd(DAC_Channel_1, ENABLE); // 使能DMA请求 } /** * DMA 配置(用于将波形数据传送到 DAC) */ void DMA_Configuration(void) { DMA_InitTypeDef DMA_InitStructure; DMA_DeInit(DMA1_Channel3); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(DAC->DHR12R1); // DAC 数据寄存器 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)current_wave; // 当前波形地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = WAVE_TABLE_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel3, &DMA_InitStructure); DMA_Cmd(DMA1_Channel3, ENABLE); } /** * 动态更新 DMA 内存地址(切换波形或幅度后调用) */ void Update_DMA_Address(uint16_t* new_addr) { DMA_Cmd(DMA1_Channel3, DISABLE); DMA_DeInit(DMA1_Channel3); DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(DAC->DHR12R1); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)new_addr; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = WAVE_TABLE_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel3, &DMA_InitStructure); DMA_Cmd(DMA1_Channel3, ENABLE); } /** * TIM2 配置:生成定时中断以触发 DAC */ void TIM2_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // 设置定时器周期和预分频 TIM_TimeBaseStructure.TIM_Period = frequency_level; // 自动重载值 TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // 72MHz / 72 = 1MHz 计数频率 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // 设置 TRGO 信号为更新事件,用于触发 DAC TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); // TIM_Cmd(TIM2, ENABLE); // 在 main 中启动更清晰 } /** * 按键读取函数(0~4 对应五个按键) * @param key_num: 按键编号 (0=PA15, 1=PB4, 2=PB5, 3=PB6, 4=PB7) * @return 按键电平状态(0 表示按下) */ int Read_Key(int key_num) { static const uint16_t pins[5] = { GPIO_Pin_15, GPIO_Pin_4, GPIO_Pin_5, GPIO_Pin_6, GPIO_Pin_7 }; static const GPIO_TypeDef* ports[5] = { GPIOA, GPIOB, GPIOB, GPIOB, GPIOB }; if (key_num >= 0 && key_num < 5) { return (int)GPIO_ReadInputDataBit((GPIO_TypeDef*)ports[key_num], pins[key_num]); } return 1; // 默认未按下 } /** * 简单延时函数(基于循环) * @param ms 延时毫秒数(@72MHz 约每ms 72000次循环) */ void delay_ms(uint32_t ms) { uint32_t i, j; for (j = 0; j < ms; j++) for (i = 0; i < 72000; i++); } 设备配置应该勾选什么
最新发布
12-19
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值