本帖最后由 229382777@qq.com 于 2017-2-28 10:58 编辑
买了原子的mini开发板快一年了,一直都是断断续续的学,学习进度经常被打断,导致现在连前面的知识也忘的差不多了,自身学习的条件可能没有大学生好,即将面临毕业实习,希望在最后这两个月能把mini教程全部过完并掌握,争取出去后能适应的了这方面的工作。在此借原子哥的宝地一用,也方便自己日后的复习,学习过程中可能会出现挺多错误的地方,也希望大家能帮忙指出其中错误的地方。为了保证自己的身体健康,不忙的情况下一般都会晚上9点前进行更新,每天会坚持去操场跑步。希望各位也注重身体健康,身体是革命的本钱O(∩_∩)O!
目录
所在页数 所在楼层楼层主题 1
1
1
1
1
1
1
1
2
2
2
2
2
2
2
2
3
3
3
3
3
3
3
3
4
4
4
4
4
4
4
4
4
4
4
42#
20#
25#
32#
38#
41#
44#
46#
54#
59#
60#
63#
71#
78#
85#
86#
100#
106#
110#
117#
122#
134#
144#
148#
152#
154#
155#
158#
163#
164#
167#
171#
173#
176#
185#
189#之后硬件篇
SYSTEM文件部分(一)
SYSTEM文件部分(二)
LED灯
按键
串口
外部中断
独立、窗口看门狗
定时器中断
PWM互补输出及死区时间
输入捕获
OLED
LCD
LCD(二)
RTC
待机唤醒
ADC
内部温度传感器
DAC
DMA
IIC
SPI
触摸屏
FLASH模拟EEPROM
内存管理
SD卡
FATFS
汉字显示实验
图片显示
IAP
触控USB鼠标实验
M3内核基础知识
UCOS任务调度
UCOS信号量和邮箱
消息队列、信号量、软件定时器
知识点分享
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
今天没事移植了下UCGUI,不带系统的移植,比较简单,需要的可以看下以下四个链接,有一个是原子哥提供的GUI源码,另外三个是关于移植的,关于API的应用板子暂时不在身边这试不了,带系统的移植有时间再玩一下
http://www.openedv.com/posts/list/522.htm
http://www.openedv.com/thread-20610-1-1.html
http://blog.chinaunix.net/uid-361890-id-2981509.html
http://wenku.baidu.com/link?url= ... jJQYApkkn8aEhPBq-aG
实战:DMA
简介:
DMA,全称为:Direct Memory Access,即直接存储器访问。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使CPU的效率大为提高。
STM32 最多有2个DMA控制器(DMA2仅存在大容量产品中), DMA1有7个通道。DMA2有 5个通道。每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁起来协调各个DMA请求的优先权。
● 12个独立的可配置的通道(请求): DMA1有7个通道, DMA2有5个通道
● 每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置。
● 在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推) 。
● 独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。
● 支持循环的缓冲器管理
● 每个通道都有3个事件标志(DMA半传输、 DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求。
● 存储器和存储器间的传输
● 外设和存储器、存储器和外设之间的传输
● 闪存、 SRAM、外设的SRAM、 APB1、 APB2和AHB外设均可作为访问的源和目标。
● 可编程的数据传输数目:最大为65535
下面为功能框图:
本次实验用到的ADC1是通道1
自己将原子哥的例程实验后,将DMA和ADC、DAC进行了结合,原子哥的例程是通过DMA读取数据到串口发送到电脑显示,并且通过寄存器的递减来显示传递的进度然后在电脑显示,实现这个功能后,自己又对前面两章学习的内容进行了结合,设置4个ADC通道,2路DAC输出,DMA进行数据传递,并且给LCD增加了新的功能,下面介绍DMA需要配置的几个寄存器
DMA中断状态寄存器(DMA_ISR)
这次自己分别试了下使用中断和不使用中断,都没有问题,下面说下不使用中断的配置
DMA_GetFlagStatus(DMA1_FLAG_TC1)!=RESET //等待通道1传输完成DMA中断标志清除寄存器(DMA_IFCR)
DMA_ClearFlag(DMA1_FLAG_TC1);//清除通道1传输完成标志DMA通道x配置寄存器(DMA_CCRx)(x = 1…7)
DMA_InitStruct.DMA_BufferSize = cndtr; //设置为4,有4个通道的ADC数据
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;//外设通过DMA向内存存入数据
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable; //DMA通道x不设置为内存到内存传输
DMA_InitStruct.DMA_MemoryBaseAddr = cmar; //DMA内存基地址
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; //循环DMA模式(适合ADC扫描类)
DMA_InitStruct.DMA_PeripheralBaseAddr = cpar; //DMA外设ADC基地址
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStruct.DMA_Priority=DMA_Priority_High; //DMA通道优先级高
DMA_Init(DMA_CHx, &DMA_InitStruct);
DMA_Cmd(DMA1_Channel1,ENABLE); //使能DMA1通道1传输DMA通道x外设地址寄存器(DMA_CPARx)(x = 1…7)
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据位宽16位(AD转换数据为16位)DMA通道x存储器地址寄存器(DMA_CMARx)(x = 1…7)
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//内存数据位宽16位设置扫描模式,不用每次都用单次转换和读取一个规则通道的值了,那样的话必须按顺序来读,而用ADC的扫描模式则可以设置ADC的采样顺序了.
ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;//开启连续转换
ADC_InitStruct.ADC_ScanConvMode = ENABLE;//开启扫描模式
ADC_InitStruct.ADC_NbrOfChannel = 4;//顺序进行规则转换的ADC通道的数目
//设置4通道的采样顺序和采样时间(可以更改)
ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1,ADC_Channel_2,3,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1,ADC_Channel_3,4,ADC_SampleTime_239Cycles5);最后设置一个数组来保存ADC_DR寄存器的4个通道值
ADC_ConvertedValue[4];
MY_DMA_Init(DMA1_Channel1, (u32)&ADC1->DR, (u32)ADC_ConvertedValue, 4);//传递进形参地址
关于LCD的新功能就是将printf函数重映像到屏幕上,之前试过没有x,y轴定位的方式,但是实际意义不大,这次修改了一下可以支持定位操作了,实现的方法来自于论坛的网友提供,对于原子哥之前要取出整数和小数部分显得比较麻烦,所以用printf的%f直接输出就可以了,以后直接可以用屏幕来打印信息了,免得开串口那么麻烦,哈哈,懒人神技!
[mw_shl_code=c,true]//重定义fputc函数 int fputc(int ch, FILE *f) { static u16 x=0, y=0; if(ch == ' ') { x = 0; y += 12; return ch; } if(x > 240-6) { x = 0; y += 12; } if(y > 320-12) { y = 0; LCD_Clear(WHITE); } LCD_Show_Char(x, y, ch, 12); x+=6; return ch; } #include <stdarg.h>//加入头文件[/mw_shl_code] [mw_shl_code=c,true]void LCD_ShowString(u16 x,u16 y,const u8 *p) { u16 x1; x1=x; while(*p!=' ') { if(x>=lcddev.width){x=x1;} if(y>=lcddev.height){y=x=0;LCD_Clear(WHITE);} if(*p==' ') { y+=16; x=x1; } else { LCD_Show_Char(x,y,*p,16); x+=8; } p++; } } void LCD_printf(u16 x,u16 y,const char *format, ...) { char tmp[25]; __va_list arg; va_start(arg, format); vsprintf(tmp,format,arg); va_end(arg); LCD_ShowString(x,y,(const u8*)tmp); }[/mw_shl_code]printf重定向函数:
DAC输出:
Dac1_Set_Vol(1500); //1.5V
Dac2_Set_Vol(2100); //2.1V
ADC获取:
adcx = ADC_ConvertedValue;
temp = (float)adcx*(3.3/4096);
LCD_printf(96, 40+i*16, "%1.3fV", temp);
算出值后直接定位打印出来就好了,非常方便,下面是例程的效果图,4路ADC+2路DAC+DMA的效果(本章代码在附件中,有需要的可以参考下)帖子从排版、内容质量都很棒,坚持下去必有很大提升~~~~~
楼主作息很规律啊,我都计划好几个月作息依然艰难于执行,向你学习~~~~~
一周热门 更多>