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

智能推荐

java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationB-程序员宅基地

文章浏览阅读788次。搭建spring cloud的时候,报以下错误:java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.<init>([Ljava/lang/Object;)V 是由于spring boot版本兼容性导致的,在pom.xml中修改配置文件,修改前:..._nosuchmethoderror: 'void org.springframework.boot.builder.springapplicationb

去除全局设置的box-sizing:border-box_box-sizing去除-程序员宅基地

文章浏览阅读4.1k次。只需要给不需要box-sizing:border-box的元素上加上box-sizing:content-box 就行_box-sizing去除

JavaWeb(14) 页面静态化之使用freemarker模板生成一个html静态页面_java实现静态模板-程序员宅基地

文章浏览阅读6.2k次。题外话: 页面静态化(展示数据从JSP页面变成HTML页面)实现方式-->模板技术 从本质上来讲,模板技术是一个占位符动态替换技术。一个完整的模板技术需要四个元素:①模板语言(使用的语法) ②包含模板语言的模板文件(.ftl结尾) ③模板引擎(jar包)④拥有动态数据的数据对象 FreeMarker是一款模板引擎:即一种基于模板和要改变的数据,并用来..._java实现静态模板

CRC16-CCITT校验算法实现(C#版)_c# static byte[] datacrc16_ccitt-程序员宅基地

文章浏览阅读6.4k次。public ushort[] CRC16Table = { 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,_c# static byte[] datacrc16_ccitt

android 图片压缩避免内存溢出的解决办法-程序员宅基地

文章浏览阅读462次。在android中的很多应用中都需要拍照上传图片,随着手机的像素越来越高,拍摄的图片也越来越大。在拍摄后显示的时候,使用universalimageloader.这个开源项目可以避免内存溢出。但是在上传的时候,一般需要压缩,但是压缩的时候很容易导致内存溢出。解决的办法就是,压缩后的二进制流,不用导出Bitmap,而是直接存储为本地文件,上传的时候直接通过本地文件上传。代码如下:1.图片压缩获..._android压缩图片会造成内存溢出

Subnet简介-程序员宅基地

文章浏览阅读2.9w次,点赞2次,收藏13次。Subnet(子网)在一般的概念中,有两个基本含义:1 这个子网的网段(CIDR)和IP版本;2 这个子网的路由(含默认路由)。事实上,Subnet模型也确实有这两个字段cidr和ip_version,分别表示一个子网的网段和IP版本。另外Subnet模型还有两字段gateway_ip和host_routes,表示一个子网的路由信息。gateway_ip是这个子网的默认网关IP。host_rout..._subnet

随便推点

Ubuntu20下安装QT5.9_qt-opensource-linux-x64-5.9.0.run-程序员宅基地

文章浏览阅读977次。安装c语言和c++环境在终端中输入sudo apt-get install gccsudo apt-get install g++使用清华开源软件镜像进行下载https://mirrors.tuna.tsinghua.edu.cn/qt/archive/qt/5.9/5.9.0/进入下载文件所在的位置,进入终端执行命令chmod +x qt-opensource-linux-x64-5.9.0.run然后点开刚刚那个安装包下载即可(这里我全部勾选安装了)安装统一字体配置库_qt-opensource-linux-x64-5.9.0.run

opencv-python常用函数解析及参数介绍(八)——轮廓与轮廓特征_python opencv提取圆轮廓-程序员宅基地

文章浏览阅读986次,点赞2次,收藏9次。在前面的文章中我们已经学会了使用膨胀与腐蚀、使用梯度、使用边缘检测的方式获得图像的轮廓,那么在获得轮廓后我们可以对图像进行什么样的操作呢?本文将介绍轮廓的绘制与轮廓特征的使用。_python opencv提取圆轮廓

linux redis自动关闭问题_linux redis启动 linux redis启动一会后自动关闭-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏5次。linux 自动关闭的问题问题:redis.clients.jedis.exceptions.JedisDataException: MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured_linux redis启动 linux redis启动一会后自动关闭

【SpringCloud-Alibaba系列教程】14.一文教你入门RocketMQ_《芋道 spring cloud alibaba 消息队列 rocketmq 入门-程序员宅基地

文章浏览阅读560次。<本文已参与 RocketMQ Summit 优秀案例征文活动,点此了解详情>MQ简介MQ(Message Queue)是一种跨进程的通信机制,用于消息传递。通俗点说,就是一个先进先出的数据结构。MQ应用场景异步解耦很多场景不使用MQ会产生各个应用见紧密耦合在在一起,其实我们要遵循的原则就是高内聚低耦合,通过上图我们就可以看到,消息生产者,不管消息消费者状态如何,生产好的消息就直接投递到MQ中,消息消费者也是同样,不管消息生产者如何,只取MQ中的消息进行处理。这是解耦.._《芋道 spring cloud alibaba 消息队列 rocketmq 入门

基于微信小程序的校园导航小程序设计与实现_简单的校园导航微信小程序怎么弄-程序员宅基地

文章浏览阅读1k次,点赞23次,收藏41次。今天带来的是基于SpringBoot的校园导航微信小程序设计与实现,智能化的管理方式可以大幅降低学校的运营人员成本,实现了校园导航的标准化、制度化、程序化的管理,有效地防止了校园导航的随意管理,提高了信息的处理速度和精确度,能够及时、准确地查询和修正建筑速看等信息。课题主要采用微信小程序、SpringBoot架构技术,前端以小程序页面呈现给学生,结合后台java语言使页面更加完善,后台使用MySQL数据库进行数据存储。微信小程序主要包括学生信息、校园简介、建筑速看、系统信息等功能。_简单的校园导航微信小程序怎么弄

The server time zone value ‘�й���׼ʱ��‘ is unrecognized or represents more than one time zone.-程序员宅基地

文章浏览阅读33次。java.sql.SQLException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone.