2021-06-05 GD32F405VG 调试过程关于DAC/DMA/TIMER等问题的解决_dac1和dac0不能同时使用-程序员宅基地

技术标签: stm32  嵌入式  STM32调试BUG记录  单片机  

GD32F405VG 调试过程关于DAC/DMA/TIMER等问题的解决

GD32F405与STM32F405外设完全兼容,外设的地址映射也是完全兼容。ST的标准库中的名字与GD32的外设名字不一致,比如STM32中的TIMER1的地址映射,对应的是GD32的TIMER0,STM32的DAC1对应GD32的DAC0,等等诸如此类。

STM32F405的程序直接烧写到GD32F405中,程序能够运行但部分功能异常,在STM32F405中使用TIMER6触发DAC1转换,使用DAC1的数字量通过DMA传输,程序一切正常,但是GD32运行此程序,DAC无波形产生,DAC的DMA全传输完成中断无法进入,最后发现问题所在:

STM32中配置的TIMER6对应GD32的TIMER5(暂时还是称作TIMER6),但是TIMER6始终无法触发DAC产生波形,开启TIMER6的更新中断,DEBUG模式,程序可以进入TIMER6的更新中断,DAC依然没有模拟量输出,最后抱着试一试的心态使用TIMER5触发DAC,DAC波形出现,但是DMA依然无法正常运行,刚开始认为是硬件配置有问题,最后发现是初始化顺序有问题,DAC_OUT_INIT();后面增添了一段是DAC缓慢输出到所需电压的一段代码,没有此代码时,DMA运行正常,加上此代码段后,DMA不运行,原来是DAC外设初始化后紧接着初始化了DAC的DMA功能,最后使能了DAC输出以及DAC_DMACmd(DAC_Channel_1, ENABLE)就是这一句DAC_DMACmd(DAC_Channel_1, ENABLE)使能早了,如果没有Init_Laser()这一句,使能后没有问题,有了Init_Laser()这一句,DAC的DMA功能使能了但是DMA相应的通道没有使能,使程序异常。

运行不正常的代码如下:

//DAC初始化配置
void DAC_OUT_Init(void)
{
    
	GPIO_InitTypeDef GPIO_InitStructure;
	DAC_InitTypeDef DAC_InitStructure;
	DMA_InitTypeDef DMA_InitStructure;
	TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);                         
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	/*DAC1 is used to generate sweep signal */
	DAC_InitStructure.DAC_Trigger = DAC_Trigger_T5_TRGO;
	DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
	DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
	DAC_Init(DAC_Channel_1, &DAC_InitStructure);
//	/*DAC2 is used to set laser temperature*/
	DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
	DAC_Init(DAC_Channel_2, &DAC_InitStructure);
	
	/* Time base configuration */
	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 
	TIM_TimeBaseStructure.TIM_Period = 2000-1;    // 1ms*500点   
	TIM_TimeBaseStructure.TIM_Prescaler = 42-1;       
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;    
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
	TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);

	/* TIM6 TRGO selection */
	TIM_SelectOutputTrigger(TIM5, TIM_TRGOSource_Update);
	
//	/*TIM6 IT_Update */
//	TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);

	/* TIM6 enable counter */
	TIM_Cmd(TIM5, ENABLE);

	/* DMA1_Stream5 channel7 configuration DAC1 DMA request*/
	DMA_DeInit(DMA1_Stream5);
	DMA_InitStructure.DMA_Channel = DMA_Channel_7;  
	DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_ADDRESS;
	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&DAC_DataTable;
	DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
	DMA_InitStructure.DMA_BufferSize = DAC_DATA_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_FIFOMode = DMA_FIFOMode_Disable;         
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
	DMA_Init(DMA1_Stream5, &DMA_InitStructure);
	
	/* Enable the DMA Stream5 IRQ Channel */
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;	
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	//DMA_ITConfig(DMA1_Stream5, DMA_IT_TC|DMA_IT_HT, ENABLE);//传输完成和半传输完成中断
	DMA_ITConfig(DMA1_Stream5, DMA_IT_TC, ENABLE);//传输完成和半传输完成中断
	
	DAC_Cmd(DAC_Channel_1,ENABLE);
	DAC_Cmd(DAC_Channel_2,ENABLE);
	
	DAC_DMACmd(DAC_Channel_1, ENABLE);
}

//主函数中调用
	DAC_OUT_Init();//**************************DAC初始化配置
	Init_Laser();//********************************初始化激光器,使电流缓慢上升
	DMA_Cmd(DMA1_Stream5, ENABLE);//***********DMA通道使能,输出扫描信号波形:

当更换了TIMER以后,DAC工作正常,DMA工作不正常,最后根据实验现象发现是初始化顺序出现了问题,将AC_DMACmd(DAC_Channel_1, ENABLE); 从DAC_OUT_Init();中拿出来,放在Init_Laser();之后,程序运行正常,也就是,DAC初始化完之后没有立马使用DMA传输的话,不要使能DMA传输功能,放在最后使能。

能正常运行的代码如下:

//DAC初始化配置函数
void DAC_OUT_Init(void)
{
    
	GPIO_InitTypeDef GPIO_InitStructure;
	DAC_InitTypeDef DAC_InitStructure;
	DMA_InitTypeDef DMA_InitStructure;
	TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);                         
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	/*DAC1 is used to generate sweep signal */
	DAC_InitStructure.DAC_Trigger = DAC_Trigger_T5_TRGO;
	DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
	DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
	DAC_Init(DAC_Channel_1, &DAC_InitStructure);
//	/*DAC2 is used to set laser temperature*/
	DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
	DAC_Init(DAC_Channel_2, &DAC_InitStructure);
	
	/* Time base configuration */
	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 
	TIM_TimeBaseStructure.TIM_Period = 2000-1;    // 1ms*500点   
	TIM_TimeBaseStructure.TIM_Prescaler = 42-1;       
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;    
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
	TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);

	/* TIM6 TRGO selection */
	TIM_SelectOutputTrigger(TIM5, TIM_TRGOSource_Update);
	
//	/*TIM6 IT_Update */
//	TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);

	/* TIM6 enable counter */
	TIM_Cmd(TIM5, ENABLE);

	/* DMA1_Stream5 channel7 configuration DAC1 DMA request*/
	DMA_DeInit(DMA1_Stream5);
	DMA_InitStructure.DMA_Channel = DMA_Channel_7;  
	DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_ADDRESS;
	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&DAC_DataTable;
	DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
	DMA_InitStructure.DMA_BufferSize = DAC_DATA_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_FIFOMode = DMA_FIFOMode_Disable;         
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
	DMA_Init(DMA1_Stream5, &DMA_InitStructure);
	
	/* Enable the DMA Stream5 IRQ Channel */
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;	
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	//DMA_ITConfig(DMA1_Stream5, DMA_IT_TC|DMA_IT_HT, ENABLE);//传输完成和半传输完成中断
	DMA_ITConfig(DMA1_Stream5, DMA_IT_TC, ENABLE);//传输完成和半传输完成中断
	
	DAC_Cmd(DAC_Channel_1,ENABLE);
	DAC_Cmd(DAC_Channel_2,ENABLE);
	
//	DAC_DMACmd(DAC_Channel_1, ENABLE);
}

//主函数中调用
	DAC_OUT_Init();//**************************DAC初始化配置
	Init_Laser();//****************************初始化激光器,使电流缓慢上升
	DAC_DMACmd(DAC_Channel_1, ENABLE); //2021-6-5从 DAC_OUT_Init() 函数中提取出来,放在此处,程序运行正常
	DMA_Cmd(DMA1_Stream5, ENABLE);//***********DMA通道使能,输出扫描信号波形
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_36130591/article/details/117596443

智能推荐

【C/C++】JAVA与C/C++ AES加密算法同步_botan c++ aes java 互通-程序员宅基地

文章浏览阅读4.6k次。此处我们使用的是AES的基础加密模式,即:电码本模式 ECBJAVA代码如下: //创建AES加密实例 SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "AES"); Cipher cip = Cipher.getInstance("AES/ECB/NoPadding");//算法/模式/补码方式 cip.init(C_botan c++ aes java 互通

民工哥折腾了2年多的《Linux系统运维指南》终于和大家见面了_linux系统运维指南:从入门到企业实战 pdf-程序员宅基地

文章浏览阅读2.5k次,点赞5次,收藏17次。2018年3月,我与张老师就这么在微信上聊了起来,起初我并没有写书的打算,我们之间只是通过讨论、交流的形式聊聊关于出书的方方面面。最终,敌不过张老师超强的专业能力、细致的解说与盛情相邀,我答应张老师写一本Linux系统运维的图书并由人邮出版。由此,我踏上了漫漫2年多的写书之路。为什么写这本书写书一方面是我对自己所学知识的查漏补缺过程,另一方面也可以向即将进入或已经入行的Linux系统运维同..._linux系统运维指南:从入门到企业实战 pdf

tf.reduce_sum()方法深度解析-程序员宅基地

文章浏览阅读2k次,点赞6次,收藏5次。tf.reduce_sum()函数深度解析从矩阵,数组,数据存储的角度 解析axis参数的意义_tf.reduce_sum

adb获取app包名的方法_adb获取包名-程序员宅基地

文章浏览阅读9.8k次,点赞4次,收藏29次。adb获取app包名的方法_adb获取包名

虾皮、lazada店铺运营攻略,如何搭建高效、稳定的自养号测评系统-程序员宅基地

文章浏览阅读913次,点赞16次,收藏10次。总之,要做好虾皮店铺,不仅需要明确的定位和优质的产品,还需要精心的运营和持续的改进。通过不断优化店铺形象、制定有效的营销策略、提供优质的客户服务以及加强供应链管理等手段,您将能够在激烈的竞争中脱颖而出,实现店铺的长足发展。1.稳定的网络环境是基石,它需要经过技术手段的洗礼,将电脑或手机的底层硬件参数伪装成国外数据,以躲避平台通过IP进行的深度检测。这种真实性高的评价能够帮助商家获得更多的信任和认可,从而提升产品的排名和流量的分配。您可以关注行业动态,学习先进的经营理念和技术,以提高店铺的运营水平。

统计检验问题:Friedman Test,Nemenyi test检验和Bonferroni-Dunn test检验_统计测试 cd diagrams-程序员宅基地

文章浏览阅读5k次,点赞11次,收藏43次。统计检验_统计测试 cd diagrams

随便推点

【合集】常见中间件漏洞_hrs中间件-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏37次。1. IIS1. PUT漏洞用户配置不当,exp:https://github.com/hackping/HTTPMLScan.git2. 短文件名猜解IIS的短文件名机制,可以暴力猜解短文件名,访问构造的某个存在的短文件名,会返回404,访问构造的某个不存在的短文件名,返回400。exp:https://github.com/WebBreacher/tilde_enum3.远程代码执行(CVE-2017-7269))**exp**:https://github.com/zcgonv_hrs中间件

db2基本概念-程序员宅基地

文章浏览阅读368次。DB2支持以下两种类型的表空间: 1、 系统管理存储器表空间(SMS-SYSTEM MANAGED STORAGE) 2、 数据库管理存储器表空间(DMS-DATABASE MANAGED STORAGE) SMS、DMS用户表空间的特性对照 特性 ..._db2

模拟window桌面实现-程序员宅基地

文章浏览阅读84次。正在开发中的游戏有个全屏功能--可以在window桌面背景上运行,就像一些视频播放器在桌面背景上播放一样的,花了个上午整了个Demo放出来留个纪念。实现功能:显示图标,双击图标执行相应的程序,右击图标弹出该图标对应得菜单,点击非图标区则弹出桌面菜单。需要完整工程可以点此下载:DesktopWindow.rar。程序效果图如下:在这个程序里,定义了一个XShellItem..._模拟实现windows桌面效果

https://www.byhy.net/tut/webdev/django/01/-程序员宅基地

文章浏览阅读944次。https://www.byhy.net/tut/webdev/django/01/_byhy.net

vue玩转移动端H5微信支付和支付宝支付_移动端支付宝微信支付vue项目怎么写-程序员宅基地

文章浏览阅读5.8k次,点赞13次,收藏57次。业务场景介绍:H5移动端支持微信支付 [ 微信支付分为微信内支付(JSAPI支付官方API)和微信外支付(H5支付官方API)] && 支付宝支付 [手机网站支付转 APP 支付 官方API ]订单生成逻辑:前端请求后端提交订单,后端去和微信或者支付宝对接生成订单(后续支付都是这个逻辑进行的对接)一、移动端微信支付,vue中如何玩?在移动端微信支付分为微信内支付和微信外支付。1.在订单组件中选择支付方式之后在支付页面先去判断是否是在微信内://判断是否微信 is__移动端支付宝微信支付vue项目怎么写

深度学习AI编译器-TVM简介_tvm编译器-程序员宅基地

文章浏览阅读2k次,点赞5次,收藏9次。深度学习编译器主要为解决不同框架下训练的模型部署到指定的某些设备上时所遇到的一系列复杂的问题,即将各种深度学习训练框架的模型部署到各种硬件所面临的问题;_tvm编译器

推荐文章

热门文章

相关标签