完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>

|
` 本帖最后由 zzq宁静致远 于 2013-11-21 18:37 编辑 8月初以来,在论坛,“朱兆祺带你一步一步学习嵌入式(连载)”(https://bbs.elecfans.com/jishu_357014_1_1.html)以及“朱兆祺教你如何攻破C语言学习、笔试与机试的难点(连载)”(https://bbs.elecfans.com/jishu_354666_1_1.html)得到大家的认可,说明这两个帖子对大家有很大的帮助。这两个帖子都是我接触C语言以来到现在承接单片机、ARM项目的经验总结,我希望通过这两个帖子,各位嵌入式学习者能得到正能量,以最快的方式进步。C语言这个帖子我已经引领网友进入实战项目中,我的C语言功底不是单纯传授书本知识,更重要的是能让各位领略到我这个帖子对你做项目到底有多大的用处。 网友认为,朱兆祺是不是只会编程,只会C语言,只会Linux。OK,朱兆祺趁这个国庆假期,我想此刻很多网友都在游历祖国山河,我就将使用STM32做过的项目小做一下整理,由浅入深、深入浅出,告诉你一个从未接触过STM32的学习者,怎么去做好一个项目,怎样可以代码重用,怎样给项目预留好升级空间。既然是教大家,就使用STM32最强大的那款(STM32F103ZET6、144个引脚),以这个为控制芯片。其实只要你做好模块化编程,控制芯片早已不重要(为什么?后面你会恍然大悟的)。 在进行STM32学习过程中,你们手中最好有一块STM32板子: http://item.taobao.com/item.htm?spm=a1z10.1.w137712-3105488089.8.X83zzd&id=22208871338 购买的时候告诉客服你是看到“朱兆祺STM32项目(硬件设计、软件编程)手记(连载)”购买的,只需要49元,但是每人仅能购买一块。 朱兆祺STM32项目(硬件设计、软件编程)手记(连载)正式开始。 朱兆祺STM32项目手记目录: `
第一节 STM32核心板介绍: https://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=385613&pid=2309703&fromuid=222350 第二节 STM32小试牛刀——LED: https://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=385613&pid=2309723&fromuid=222350 第三节 UART——调试帮手: https://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=385613&pid=2309734&fromuid=222350 第四节 直流电机PID控制: https://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=385613&pid=2313310&fromuid=222350 第五节 直流电机PID控制程序: https://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=385613&pid=2330272&fromuid=222350 第六节 指针函数在STM32程序中的巧妙应用 https://bbs.elecfans.com/forum.p ... ;amp;fromuid=222350 第七节 PID在智能小车中的应用 https://bbs.elecfans.com/forum.ph ... 2926&fromuid=222350 第八节 关于BOOT问题 https://bbs.elecfans.com/forum.php?mod=redirect&goto=findpost&ptid=385613&pid=2420842&fromuid=222350
|
|
相关推荐
2 条评论
190 个讨论
|
|
|
本帖最后由 dongyumin 于 2013-10-2 21:42 编辑
第一节 STM32核心板介绍 控制芯片为:STM32F103ZET6,144个引脚。在实际项目中,不是说功能越强大就选择它,而是要从芯片的优点,价格等多方面考虑。但是在这里,你们学习必须要一个载体,折中即选择它了。图片见附件1:STM32F103ZET6 引脚定义。图片见附件2:引脚定义。 在每个STM32的芯片上都有两个管脚BOOT0和BOOT1(PB2),这两个管脚在芯片复位时的电平状态决定了芯片复位后从哪个区域开始执行程序。 (1)BOOT1=xBOOT0=0从用户闪存启动,这是正常的工作模式。 (2)BOOT1=0BOOT0=1从系统存储器启动,这种模式启动的程序功能由厂家设置。 (3)BOOT1=1BOOT0=1从内置SRAM启动,这种模式可以用于调试。 大家可以通过跳冒的连接设置不同的执行程序,一般BOOT0和BOOT1(PB2)跳线都跳到GND(地)。 图片见附件3:BOOT。 这里LED采用灌入式驱动,R = (3.3V - V(LED))/ (LED的驱动电流),这就是LED电阻的算法,这个是限流电阻。大家记得举一反三。 图片见附件4:LED。 复位电路,右边引脚是连接NRST,当电源一上电,由于电阻两端电压不能突变,此时NRST为低电平,此时STM32芯片复位;当充电到高电平(一般来说到1.8V就认为是高电平),STM32工作;当你需要对其复位,按下KEY,NRST被拉为低电平,复位。 图片见附件5:复位电路。 这是USB供电电路与USB驱动电路。 图片见附件6:USB。 至于其他功能我们在往后接触到了再一一讲解。 |
|
|
|
|
|
|
|
|
本帖最后由 zzq宁静致远 于 2013-10-12 09:47 编辑
第二节 STM32小试牛刀——LED 这是基本上所有的学习者第一步学习的程序,因为简单。但是我看过的程序都是千篇一律,其实再简单的一个程序都要注重模块化编程,这是朱兆祺要告诉大家的第一个经验,因为只有这样,你的代码才能复用。 我们看下最底层我们的配置,这一层是直接和底层硬件打交道: /******************************************************************** ** 函数名称:LED_Configuration ** 函数功能:对LED1-LED5的配置 ** 入口参数:None ** 出口参数:None ********************************************************************/ void LED_Configuration (void) { /* LED_InitStructure structure typedef struct { u16 GPIO_Pin; GPIOSpeed_TypeDef GPIO_Speed; GPIOMode_TypeDef GPIO_Mode; } GPIO_InitTypeDef ; */ GPIO_InitTypeDef GPIO_InitStructure; /* Configure all unused GPIO port pins in Analog Input mode (floating input trigger OFF), this will reduce the power consumption and increase the device immunity against EMI/EMC *************************************************/ /* 将GPIOA、GPIOB、GPIOC、GPIOD、GPIOE使能 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; /* void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) 根据GPIO_InitStruct中指定的参数初始化外设GPIOx寄存器 */ #if 0 GPIO_Init(GPIOA | GPIOB | GPIOC | GPIOD | GPIOE , &GPIO_InitStructure) ; #endif #if 1 GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_Init(GPIOE, &GPIO_InitStructure); #endif /* 将GPIOA、GPIOB、GPIOC、GPIOD、GPIOE禁能 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, DISABLE); #ifdef USE_STM3210E_EVAL RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG, ENABLE); GPIO_Init(GPIOF, &GPIO_InitStructure); GPIO_Init(GPIOG, &GPIO_InitStructure); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG, DISABLE); #endif /* USE_STM3210E_EVAL */ /* Configure IO connected to LD1, LD2, LD3 and LD4 leds *********************/ /* Enable GPIO_LED clock */ /* #define GPIO_LED GPIOF #define RCC_APB2Periph_GPIO_LED RCC_APB2Periph_GPIOF 使能GPIOF */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO_LED, ENABLE); /* GPIOF的678910四个引脚控制五个LED 0000 0000 0000 0000 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIO_LED, &GPIO_InitStructure); /* void GPIO_Write(GPIO_TypeDef* GPIOx, u16 PortVal) 向指定GPIO数据端口写入数据 GPIOx:x可以是A,B,C,D或者E,来选择GPIO外设 PortVal: 待写入端口数据寄存器的值 */ GPIO_Write(GPIOF, 0xffff); } 底层文件配置完成之后,中间层是作为底层硬件和上层应用之间的枢纽: #ifndef _LEDCONFIG_H_ #define _LEDCONFIG_H_ /* 包含配置文件 */ #include "stm32f10x_lib.h" #include "platform_config.h" /* 连接LED1引脚输出高电平,即LED1熄灭 */ #define LED1OFF() GPIO_SetBits(GPIO_LED , GPIO_Pin_6) /* 连接LED1引脚输出低电平,即LED1点亮 */ #define LED1ON() GPIO_ResetBits(GPIO_LED , GPIO_Pin_6) /* 连接LED2引脚输出高电平,即LED2熄灭 */ #define LED2OFF() GPIO_SetBits(GPIO_LED , GPIO_Pin_7) /* 连接LED2引脚输出低电平,即LED2点亮 */ #define LED2ON() GPIO_ResetBits(GPIO_LED , GPIO_Pin_7) /* 连接LED3引脚输出高电平,即LED3熄灭 */ #define LED3OFF() GPIO_SetBits(GPIO_LED , GPIO_Pin_8) /* 连接LED3引脚输出低电平,即LED3点亮 */ #define LED3ON() GPIO_ResetBits(GPIO_LED , GPIO_Pin_8) /* 连接LED4引脚输出高电平,即LED4熄灭 */ #define LED4OFF() GPIO_SetBits(GPIO_LED , GPIO_Pin_9) /* 连接LED4引脚输出低电平,即LED4点亮 */ #define LED4ON() GPIO_ResetBits(GPIO_LED , GPIO_Pin_9) /* 连接LED5引脚输出高电平,即LED5熄灭 */ #define LED5OFF() GPIO_SetBits(GPIO_LED , GPIO_Pin_10) /* 连接LED5引脚输出低电平,即LED5点亮 */ #define LED5ON() GPIO_ResetBits(GPIO_LED , GPIO_Pin_10) #endif 作为顶层文件,是单独的一个文件,这一层所要具备的是不管放在什么平台、什么系统下面都可以运行。 int main(void) { #ifdef DEBUG debug(); #endif /* 系统时钟配置 */ RCC_Configuration(); /* 中断向量配置 */ NVIC_Configuration(); /* LED配置 */ LED_Configuration(); while (1) { LED1ON(); } } 通过这个程序,你看到了是哪个引脚在控制LED灯吗?不知道,那么,我换一个平台是不是照样可以运行。其实还可以进一步进行包装,但是要注意,是不是模块化怎么样就怎么样,非也,技术含量就在于此。 |
|
|
|
|
|
|
|
|
本帖最后由 zzq宁静致远 于 2013-10-12 09:51 编辑
第三节 UART——调试帮手 是不是改到定时器了,对,这是惯例,朱兆祺不是一个走惯例的人,UART,因为这个东西,会给你输出你想要的任何东西,这样你才能了解STM32此刻在干什么。比如你在追你的女神,你压根就不知道别人在想什么,你拿什么去追?用钱去砸还是死皮赖脸纠缠人家。知己知彼方能百战不殆。我将我想要的信息全部通过UART打印出来,我就不信我不知道你在想什么做什么。 按照我们上一节的模块化思想,最底层为configuration.c文件,我们可以将所有底层配置都放在这个文件中,作为底层驱动文件。 /******************************************************************** ** 函数名称:UART1_Configuration ** 函数功能:对UART1的配置 ** 入口参数:None ** 出口参数:None ********************************************************************/ void UART1_Configuration (void) { /* typedef struct { u32 USART_BaudRate; u16 USART_WordLength; u16 USART_StopBits; u16 USART_Parity; u16 USART_Mode; u16 USART_HardwareFlowControl; } USART_InitTypeDef; */ USART_InitTypeDef USART_InitStructure; /* typedef struct { u16 USART_Clock; u16 USART_CPOL; u16 USART_CPHA; u16 USART_LastBit; } USART_ClockInitTypeDef; */ USART_ClockInitTypeDef USART_ClockInitStructure; /* 将GPIOA_Pin9和GPIOA_Pin10设置为UART模式 */ GPIO_InitTypeDef GPIO_InitStructure; /* Enable USARTx clocks */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_AFIO, ENABLE); /* 打开GPIOA时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE) ; /* Configure USART1 Tx (PA.09) as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; /* 复用推挽输出 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART1 Rx (PA.10) as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; /* 浮空输入 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); /****************************************************** UART的配置 ******************************************************/ /* USART_CLOCK提示了USART时钟使能还是失能 USART_Clock_Enable :时钟高电平活动 USART_Clock_Disable:时钟低电平活动 */ USART_ClockInitStructure.USART_Clock = USART_Clock_Disable; /* USART_CPOL指定了SLCK引脚上时钟输出的极性 USART_CPOL_High:时钟高电平 USART_CPOL_Low :时钟低电平 */ USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low; /* USART_CPHA指定了下SLCK引脚上时钟输出的相位, 和CPOL位一起配合来产生用户希望的时钟/数据的采样关系。 USART_CPHA_1Edge:时钟第一个边沿进行数据捕获 USART_CPHA_2Edge:时钟第二个边沿进行数据捕获 */ USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge; /* USART_LastBit来控制是否在同步模式下, 在SCLK引脚上输出最后发送的那个数据字 (MSB)对应的时钟脉冲。 USART_LastBit_Disable:最后一位数据的时钟脉冲不从SCLK输出 USART_LastBit_Enable :最后一位数据的时钟脉冲从SCLK输出 */ USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable; /* Configure the USART1 synchronous paramters */ USART_ClockInit(USART1, &USART_ClockInitStructure); /* 该成员设置了USART传输的波特率 */ USART_InitStructure.USART_BaudRate = 115200; /* USART_WordLength提示了在一个帧中传输或者接收到的数据位数 USART_WordLength_8b:8位数据 USART_WordLength_9b:9位数据 */ USART_InitStructure.USART_WordLength = USART_WordLength_8b; /* USART_StopBits定义了发送的停止位数目 USART_StopBits_1:在帧结尾传输1个停止位 USART_StopBits_0.5:在帧结尾传输0.5个停止位 USART_StopBits_2:在帧结尾传输2个停止位 USART_StopBits_1.5:在帧结尾传输1.5个停止位 */ USART_InitStructure.USART_StopBits = USART_StopBits_1; /* USART_Parity定义了奇偶模式 USART_Parity_No:奇偶失能 USART_Parity_Even:偶模式 USART_Parity_Odd:奇模式 */ USART_InitStructure.USART_Parity = USART_Parity_No ; /* USART_HardwareFlowControl指定了硬件流控制模式使能还是失能 USART_HardwareFlowControl_None:硬件流控制失能 USART_HardwareFlowControl_RTS:发送请求RTS使能 USART_HardwareFlowControl_CTS:清除发送CTS使能 USART_HardwareFlowControl_RTS_CTS:RTS和CTS使能 */ USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; /* USART_Mode指定了使能或者失能发送和接收模式 USART_Mode_Tx:发送使能 USART_Mode_Rx:接收使能 */ USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; /* Configure USART1 basic and asynchronous paramters */ USART_Init(USART1, &USART_InitStructure); //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* Enable USART1 */ USART_Cmd(USART1, ENABLE); } 接下来是中间枢纽: #include "stm32f10x_lib.h" #include "platform_config.h" #include "UART1Config.h" #include /******************************************************************** ** 函数名称:UART1SendByte ** 函数功能:UART1字节发送数据 ** 入口参数:None ** 出口参数:None ********************************************************************/ void UART1SendByte(unsigned short int usiData) { while (!(USART1->SR & USART_FLAG_TC)); USART_SendData(USART1, usiData); } /******************************************************************** ** 函数名称:UART1Write ** 函数功能:UART1写数据 ** 入口参数:None ** 出口参数:None ********************************************************************/ void UART1Write(unsigned char *ucpData, unsigned short int usiLen) { u16 i; for (i=0; i UART1SendByte(ucpData); } } /******************************************************************** ** 函数名称:fputc ** 函数功能: ** 入口参数:None ** 出口参数:None ********************************************************************/ int fputc(int ch, FILE *f) { /* Write a character to the USART */ USART_SendData(USARTx, (unsigned char)ch); /* Loop until the end of transmission */ while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET) { } return ch; } 最后顶层为应用层: /* UART1配置 */ UART1_Configuration(); UART1Write((unsigned char*)"rn串口初始化成功.....rn", sizeof("串口初始化成功.....")) ; 我在这里再次强调模块化编程思想的重要性,这个思想不仅能让你的程序瞬间逆袭,还能为你以后的编程达到事半功倍的效果。 评分 |
|
|
|
|
|
|
|
|
初学者,必须赞一个
|
|
|
|
|
|
|
|
|
第四节 直流电机PID控制
直流电机控制,要想精准、闭环控制,那么肯定少不了PID控制。网友看到这里是不是该疑惑了,你不是学习嵌入式Linux的嘛?你怎么懂工业控制呢,别忘了,我的专业是自动化,自动化中最经典的代表专业课程是运动控制原理,这课程可以说是PID控制的根本。 这一节,我通过PCB设计到PID程序,一一给你解剖清楚。控制组在全国电子设计竞赛中占有比较重要的分量,在校做控制组的学生们,这一节对你们绝对分量十足。在工业控制中,PID调节更是举足轻重。以我多年做控制的经验,以驱动两个直流电机为导航,深入解析下直流电机的PID控制。其实在很多环境下都要使用到PID调节,学会PID调节,百益而无一害。 直流电机驱动原理图见附件:直流电机驱动原理图。 使用L298控制两个直流电机。 PID程序见下节,精彩继续。 |
|
|
|
|
|
|
|
你正在撰写讨论
如果你是对讨论或其他讨论精选点评或询问,请使用“评论”功能。
STM32F405驱动DS1302时钟模块,输出时间错乱该怎么排查?
2810 浏览 2 评论
stm32f405rgt6驱动DS1302ZN出现时间错乱问题
2420 浏览 1 评论
stm32用fsmc读取ad7606采集数据,数据不变,只有开发版复位才更新数据
2288 浏览 0 评论
2404 浏览 1 评论
1643 浏览 1 评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-2 12:40 , Processed in 1.106705 second(s), Total 83, Slave 74 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
10147