因为有过嵌入式开发的基础,所以多少还是了解一些,比方JTAG调试、串口下载等等概念,但也奈何长时间不接触这方面的项目,渐渐也就生疏了!
嵌入式开发相对来说需要有硬件和软件的基础知识,相对来说综合技能要求高,所以,在硬件方面没有模拟电路或者数字电路基础,软件没有C语言基础的同学建议把这三个课程补一补,然后开始嵌入式开发学习;
【公开课程】推荐大家先学习开放课程:电子科技大学,漆强老师主讲的 基于STM32CubeMX和HAL驱动库的嵌入式系统设计 !
硬件准备,需要一定的投入:
1、ARM开发板,主流的是STM32f1/STM32f4系列开发板,STM32F1系列的开发板相对要便宜很多,建议入门可以先选F1系列开发板, 可以在淘宝搜索STM32 nucleo开发板,或者正点原子的STM32开发板等等,他们提供的配套学习资料还是非常丰富的;
2、J-Link 仿真器或者ST-Link V2调试器、USB-TTL、简单万用表(用来量个电压什么的),各种排线,烙铁等等;
3、软件
Keil 5(单片机集成开发环境)
STM32CubeMX(自动配置stm32编程的相关文件)
如果是j-link仿真器或者是ST-link调试器,则不用串口下载器
FLYMCU(stm32串口下载软件,也可用ST-LINK代替)
XCOM(串口监视器)
4、参考漆强老师的课程,完成包括通用GPIO控制,中断系统,定时器,串口通信几个章节的学习,恭喜你,算是入了嵌入式开发的门了!
----
2021年2月7号更新
实现两个功能:
1、通过定时器,实现LED闪烁;
2、实现printf重定向到串口输出;
教训:
昨天使用外部电源给模块供电,之前这个供电电源已经调好了3.3V输出,所以每次只用接上就好了,这次接上后模块开发板直接冒烟了,第一时间反应肯定是烧了,断开接上没反应,确认是烧了,再一看电源,20V输出,天啦,不烧才怪!而且一次赔了两个模块!粗心大发了!
上代码:
#include "stm32f10x.h"
#include <stdio.h>
#include <string.h>
#include "stm32100b_eval.h"
static volatile uint8_t timerFlag = 0;
//Tout=((arr+1)*(psc+1))/Ft us.
/*
10000 -> 10 1ms
TIM3_Init(9999, 7199); ->1s
1
72e-6 / (7199+1) = 1e-4 (s) -> 0.1ms
*/
void TIM3_Init(uint16_t ms)
{
/*
*/
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //???????
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //??IRQ??
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //???????
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //????
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //???IRQ????????
NVIC_Init(&NVIC_InitStructure);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Period = ms*10; //???????????????????????????? ???0x0000-0xFFFF
TIM_TimeBaseStructure.TIM_Prescaler =(7200-1); //??????? TIMx ???????????
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_Trigger,ENABLE);//?????? TIM ???,?????1
TIM_Cmd(TIM3, ENABLE);
}
void ctlLed(){
uint8_t ledFlag = timerFlag;
if (ledFlag == 1){
STM_EVAL_LEDOn(LED1);
}else{
STM_EVAL_LEDOff(LED1);
}
}
void TIM3_IRQHandler(void)
{
static uint8_t flag = 0;
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //??????
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //??????
if (timerFlag){
timerFlag = 0;
}else{
timerFlag = 1;
}
ctlLed();
}
}
int main(void)
{
STM_EVAL_LEDInit(LED1);
TIM3_Init(10);//10ms闪烁一次
while(1){
deca_sleep(1000);
}
}
printf函数重定向后,使用printf输出的日志会通过串口输出到终端
/* Private function prototypes -----------------------------------------------*/
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
USART_ClearFlag(EVAL_COM1,USART_FLAG_TC);
/* e.g. write a character to the USART */
USART_SendData(EVAL_COM1, (uint8_t) ch);
/* Loop until the end of transmission */
while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TC) == RESET)
{}
return ch;
}