[STM32F1] stm32(F103c8t6)自学笔记

[复制链接]
5091|177
 楼主| t60yz 发表于 2023-11-22 11:46 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:46 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:47 | 显示全部楼层
  1. #include "stm32f10x.h"                  // Device header
  2. #include "OLED.h"
  3. #include "Bianmaqi.h"
  4. #include "Delay.h"
  5. #include "timer2.h"

  6. /***************************************************/延时函数
  7. #include "Delay.h"
  8. #include "stm32f10x.h"

  9. /**
  10.   * @brief  微秒级延时
  11.   * @param  xus 延时时长,范围:0~233015
  12.   * @retval 无
  13.   */
  14. void Delay_us(uint32_t xus)
  15. {
  16.         SysTick->LOAD = 72 * xus;                                //设置定时器重装值
  17.         SysTick->VAL = 0x00;                                        //清空当前计数值
  18.         SysTick->CTRL = 0x00000005;                                //设置时钟源为HCLK,启动定时器
  19.         while(!(SysTick->CTRL & 0x00010000));        //等待计数到0
  20.         SysTick->CTRL = 0x00000004;                                //关闭定时器
  21. }

  22. /**
  23.   * @brief  毫秒级延时
  24.   * @param  xms 延时时长,范围:0~4294967295
  25.   * @retval 无
  26.   */
  27. void Delay_ms(uint32_t xms)
  28. {
  29.         while(xms--)
  30.         {
  31.                 Delay_us(1000);
  32.         }
  33. }

  34. /**
  35.   * @brief  秒级延时
  36.   * @param  xs 延时时长,范围:0~4294967295
  37.   * @retval 无
  38.   */
  39. void Delay_s(uint32_t xs)
  40. {
  41.         while(xs--)
  42.         {
  43.                 Delay_ms(1000);
  44.         }
  45. }

  46. /***************************************************/编码器
  47. #include "stm32f10x.h"                  // Device header
  48. #include "Bianmaqi.h"

  49. void Bianmaqi_init(void)
  50. {
  51.         //1**使能时钟
  52.         RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM3,ENABLE);
  53.         RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA,ENABLE);
  54.        
  55.         //2**定义GPIO
  56.         GPIO_InitTypeDef GPIO_InitStruct;
  57.         GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
  58.         GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6 |GPIO_Pin_7;
  59.         GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
  60.         GPIO_Init(GPIOA,&GPIO_InitStruct);
  61.        
  62.         //3**初始化时基单元
  63.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  64.         TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_Channel_1|TIM_Channel_2;
  65.         TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CKD_DIV1;
  66.         TIM_TimeBaseInitStruct.TIM_Period=65536-1;
  67.         TIM_TimeBaseInitStruct.TIM_Prescaler=1-1;
  68.         TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;
  69.         TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
  70.        
  71.         //4**初始化IC模块(部分)两个Pin口
  72.         TIM_ICInitTypeDef TIM_ICInitStruct;
  73.         TIM_ICStructInit(&TIM_ICInitStruct);
  74.         TIM_ICInitStruct.TIM_Channel=TIM_Channel_1;
  75.         TIM_ICInitStruct.TIM_ICFilter=0xF;
  76. //        TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Rising;
  77. //        TIM_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1;
  78. //        TIM_ICInitStruct.TIM_ICSelection=TIM_ICSelection_DirectTI;
  79.         TIM_ICInit(TIM3,&TIM_ICInitStruct);
  80.        
  81.         TIM_ICInitStruct.TIM_Channel=TIM_Channel_2;
  82.         TIM_ICInitStruct.TIM_ICFilter=0xF;
  83. //        TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Rising;
  84. //        TIM_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1;
  85. //        TIM_ICInitStruct.TIM_ICSelection=TIM_ICSelection_DirectTI;
  86.         TIM_ICInit(TIM3,&TIM_ICInitStruct);
  87.        
  88.         //5**配置编码器
  89.         TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Falling,TIM_ICPolarity_Rising);//控制极性
  90.        
  91.         //6.使能定时器TIM3
  92.         TIM_Cmd(TIM3,ENABLE);
  93. }

  94. int16_t get_cnt(void)
  95. {
  96.         int16_t temp=0;
  97.         temp=TIM_GetCounter(TIM3);
  98.         TIM_SetCounter(TIM3,0);
  99.         return temp;
  100. }

  101. /***************************************************/定时器TIM2
  102. #include "stm32f10x.h"
  103. #include "timer2.h"

  104. extern int num;
  105. void timer2_init(void)
  106. {
  107.         //**1.打开总的RCC,要配置GPIO从而传入外部时钟
  108.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//因为定时器2是通用定时器,在APB1总线上
  109.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
  110.         //**2.配置定时器接入外部时钟 同时配置外部时钟输入的引脚
  111.         TIM_InternalClockConfig(TIM2);//设置定时器2使用内部时钟,可不写,上电默认
  112.        
  113.         GPIO_InitTypeDef GPIO_InitStruct;
  114.        
  115.         GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
  116.         GPIO_InitStruct.GPIO_Pin=GPIO_Pin_12;
  117.         GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
  118.         GPIO_Init(GPIOB,&GPIO_InitStruct);
  119.        
  120.         //TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);//第二个设置分频,第三个设置触发方式,第四个设置采样频率(滤波器)
  121.         //**3.配置时基单元
  122.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  123.        
  124.         TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//设置分频
  125.         TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//设置向上l计数
  126.         TIM_TimeBaseInitStruct.TIM_Period=10000-1;//设置预装载值       //外部时钟的话用不了这么高的频率
  127.         TIM_TimeBaseInitStruct.TIM_Prescaler=7200-1;//设置预分频值
  128. //        TIM_TimeBaseInitStruct.TIM_Period=10-1;//设置预装载值
  129. //        TIM_TimeBaseInitStruct.TIM_Prescaler=2-1;//设置预分频值
  130.         TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;//高级计数器功能,重复计数器
  131.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);//初始化时基单元
  132.         TIM_ClearFlag(TIM2,TIM_FLAG_Update);//初始化时会产生标志位,需要清除
  133.         //**4.使能时基单元的中断
  134.         TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
  135.         //**5.配置NVIC
  136.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//分组
  137.        
  138.         NVIC_InitTypeDef NVIC_InitStruct;
  139.         NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;
  140.         NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  141.         NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
  142.         NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
  143.         NVIC_Init(&NVIC_InitStruct);
  144.         //**6.开始计数
  145.         TIM_Cmd(TIM2,ENABLE);

  146. }
  147. /*
  148. //配置中断函数
  149. void TIM2_IRQHandler(void)
  150. {
  151.         if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
  152.         {
  153.                 num++;
  154.         }
  155.         TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  156. }
  157. */

  158. /***************************************************/主函数
  159. int16_t speed=0;
  160. int main(void)
  161. {
  162.         timer2_init();
  163.         OLED_Init();
  164.         Bianmaqi_init();
  165.         OLED_ShowString(1,1,"Hello,my honey");
  166.         while(1)
  167.         {
  168.                 OLED_ShowSignedNum(2,1,speed,6);
  169.         }
  170. }

  171. void TIM2_IRQHandler(void)
  172. {
  173.         if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
  174.         {
  175.                 speed=get_cnt();
  176.                 Delay_ms (10);
  177.         }
  178.         TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

  179. }
 楼主| t60yz 发表于 2023-11-22 11:59 | 显示全部楼层
七、ADC模数转换
1.结构原理
1.1 介绍
31067655d7c5540426.png
 楼主| t60yz 发表于 2023-11-22 11:59 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 11:59 | 显示全部楼层
1.2 原理
采样、抽取、量化、编码

70465655d7cb3a1b24.png
 楼主| t60yz 发表于 2023-11-22 12:00 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 12:00 | 显示全部楼层
1.3 ADC结构框图

69902655d7cecb65fa.png
 楼主| t60yz 发表于 2023-11-22 12:01 | 显示全部楼层
1.4 stm32片上资源
52036655d7d011d823.png
 楼主| t60yz 发表于 2023-11-22 12:01 | 显示全部楼层
1.5 ADC工作的4种模式
1.5.1 单次转换,非扫描模式
86301655d7d0ca3389.png
 楼主| t60yz 发表于 2023-11-22 12:01 | 显示全部楼层
1.5.2 连续转换,非扫描模式

32403655d7d182aff0.png
 楼主| t60yz 发表于 2023-11-22 12:01 | 显示全部楼层
1.5.2 连续转换,非扫描模式

44658655d7d2bad0cc.png
 楼主| t60yz 发表于 2023-11-22 12:02 | 显示全部楼层
1.5.3 单次转换,扫描模式

45158655d7d3dea0d0.png
 楼主| t60yz 发表于 2023-11-22 12:02 | 显示全部楼层
1.5.4 连续转换,扫描模式

42650655d7d4a97ba8.png
 楼主| t60yz 发表于 2023-11-22 12:02 | 显示全部楼层
1.6 ADC的触发方式(软件,硬件)

49544655d7d56a3826.png
 楼主| t60yz 发表于 2023-11-22 12:02 | 显示全部楼层
1.7 ADC的数据处理、转换时间、校准
74960655d7d61677a4.png
 楼主| t60yz 发表于 2023-11-22 12:02 | 显示全部楼层
 楼主| t60yz 发表于 2023-11-22 12:03 | 显示全部楼层
2.代码配置
2.1 ADC单通道模式
单次转换、非连续模式
  1. #include "stm32f10x.h"                  // Device header
  2. #include "OLED.h"
  3. #include "ADC.h"
  4. #include "Delay.h"

  5. /***************************************************/ADC模块
  6. #include "stm32f10x.h"                  // Device header
  7. #include "ADC.h"


  8. void ADC_init(void)
  9. {
  10.         //1.先使能时钟
  11.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
  12.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  13.        
  14.         //2.设置ADC的分频
  15.         RCC_ADCCLKConfig(RCC_PCLK2_Div6);
  16.        
  17.         //3.配置GPIO口PA0
  18.         GPIO_InitTypeDef GPIO_InitStruct;
  19.         GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;
  20.         GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
  21.         GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
  22.         GPIO_Init(GPIOA, &GPIO_InitStruct);
  23.        
  24.         //4.确定规则组或注入组的通道
  25.         ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_28Cycles5);
  26.        
  27.         //5.初始化ADC
  28.         ADC_InitTypeDef ADC_InitStruct;
  29.         ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;//配置是否连续触发模式
  30.         ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;//选择数据对齐模式为右对齐
  31.         ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//选择外界触发源
  32.         ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;//配置是ADC是几个同时工作还是独立工作
  33.         ADC_InitStruct.ADC_NbrOfChannel=1;//确定要输入的组的个数
  34.         ADC_InitStruct.ADC_ScanConvMode=DISABLE;//是否连续扫描模式
  35.         ADC_Init(ADC1, &ADC_InitStruct);
  36.        
  37.         //6.打开ADC
  38.         ADC_Cmd(ADC1,ENABLE);
  39.        
  40.         //7.校准ADC
  41.         ADC_ResetCalibration(ADC1);//1.复位校准
  42.         while(ADC_GetResetCalibrationStatus(ADC1));//2.等待复位校准完成
  43.         ADC_StartCalibration(ADC1);//3.开始校准
  44.         while(ADC_GetCalibrationStatus(ADC1));//4.等待校准完成
  45. }

  46. uint16_t get_adcvalue(void)
  47. {
  48.         ADC_SoftwareStartConvCmd(ADC1,ENABLE);//触发开始ADC读值
  49.         while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);//读取EOC标志位,当转化读取完成后退出循环
  50.         return ADC_GetConversionValue(ADC1);//读取ADC寄存器,自动清除EOC标志位
  51. }

  52. /***************************************************/延时函数
  53. #include "Delay.h"
  54. #include "stm32f10x.h"

  55. /**
  56.   * @brief  微秒级延时
  57.   * @param  xus 延时时长,范围:0~233015
  58.   * @retval 无
  59.   */
  60. void Delay_us(uint32_t xus)
  61. {
  62.         SysTick->LOAD = 72 * xus;                                //设置定时器重装值
  63.         SysTick->VAL = 0x00;                                        //清空当前计数值
  64.         SysTick->CTRL = 0x00000005;                                //设置时钟源为HCLK,启动定时器
  65.         while(!(SysTick->CTRL & 0x00010000));        //等待计数到0
  66.         SysTick->CTRL = 0x00000004;                                //关闭定时器
  67. }

  68. /**
  69.   * @brief  毫秒级延时
  70.   * @param  xms 延时时长,范围:0~4294967295
  71.   * @retval 无
  72.   */
  73. void Delay_ms(uint32_t xms)
  74. {
  75.         while(xms--)
  76.         {
  77.                 Delay_us(1000);
  78.         }
  79. }

  80. /**
  81.   * @brief  秒级延时
  82.   * @param  xs 延时时长,范围:0~4294967295
  83.   * @retval 无
  84.   */
  85. void Delay_s(uint32_t xs)
  86. {
  87.         while(xs--)
  88.         {
  89.                 Delay_ms(1000);
  90.         }
  91. }

  92. /***************************************************/主函数

  93. uint16_t ADCvalue;//旋钮值
  94. float  Voltage;//转换成电压值
  95. int main(void)
  96. {
  97.         OLED_Init();
  98.         ADC_init();
  99.         OLED_ShowString(1,1,"Hello,my honey");

  100.         OLED_ShowString(2, 1, "ADValue:");
  101.         OLED_ShowString(3, 1, "Volatge:0.00V");
  102.         while(1)
  103.         {
  104.                 ADCvalue=get_adcvalue();
  105.                 Voltage = (float)ADCvalue / 4095 * 3.3;
  106.                
  107.                 OLED_ShowNum(2, 9, ADCvalue, 4);
  108.                 OLED_ShowNum(3, 9, Voltage, 1);//这里将电压值按整数部分和小数部分两部分取出来
  109.                 OLED_ShowNum(3, 11, (uint16_t)(Voltage * 100) % 100, 2);
  110.                
  111.                 Delay_ms(100);;
  112.         }
  113. }



 楼主| t60yz 发表于 2023-11-22 12:03 | 显示全部楼层
.简单实现ADC多通道
每次改变序号里的通道即可;


  1. #include "stm32f10x.h"                  // Device header
  2. #include "OLED.h"
  3. #include "ADC.h"
  4. #include "Delay.h"

  5. /***************************************************/ADC
  6. #include "stm32f10x.h"                  // Device header
  7. #include "ADC.h"


  8. void ADC_init(void)
  9. {
  10.         //1.先使能时钟
  11.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
  12.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  13.        
  14.         //2.设置ADC的分频
  15.         RCC_ADCCLKConfig(RCC_PCLK2_Div6);
  16.        
  17.         //3.配置GPIO口PA0
  18.         GPIO_InitTypeDef GPIO_InitStruct;
  19.         GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;
  20.         GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;
  21.         GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
  22.         GPIO_Init(GPIOA, &GPIO_InitStruct);
  23.        
  24.         //4.确定规则组或注入组的通道
  25. //        ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_28Cycles5);
  26.        
  27.         //5.初始化ADC
  28.         ADC_InitTypeDef ADC_InitStruct;
  29.         ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;//配置是否连续触发模式
  30.         ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;//选择数据对齐模式为右对齐
  31.         ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//选择外界触发源
  32.         ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;//配置是ADC是几个同时工作还是独立工作
  33.         ADC_InitStruct.ADC_NbrOfChannel=1;//确定要输入的组的个数
  34.         ADC_InitStruct.ADC_ScanConvMode=DISABLE;//是否连续扫描模式
  35.         ADC_Init(ADC1, &ADC_InitStruct);
  36.        
  37.         //6.打开ADC
  38.         ADC_Cmd(ADC1,ENABLE);
  39.        
  40.         //7.校准ADC
  41.         ADC_ResetCalibration(ADC1);//1.复位校准
  42.         while(ADC_GetResetCalibrationStatus(ADC1));//2.等待复位校准完成
  43.         ADC_StartCalibration(ADC1);//3.开始校准
  44.         while(ADC_GetCalibrationStatus(ADC1));//4.等待校准完成
  45. }

  46. uint16_t get_adcvalue(uint8_t ADC_Channel)
  47. {
  48.                 ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_28Cycles5);

  49.         ADC_SoftwareStartConvCmd(ADC1,ENABLE);//触发开始ADC读值
  50.         while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);//读取EOC标志位,当转化读取完成后退出循环
  51.         return ADC_GetConversionValue(ADC1);//读取ADC寄存器,自动清除EOC标志位
  52. }
  53.      
  54. /***************************************************/延时
  55. #include "Delay.h"
  56. #include "stm32f10x.h"

  57. /**
  58.   * @brief  微秒级延时
  59.   * @param  xus 延时时长,范围:0~233015
  60.   * @retval 无
  61.   */
  62. void Delay_us(uint32_t xus)
  63. {
  64.         SysTick->LOAD = 72 * xus;                                //设置定时器重装值
  65.         SysTick->VAL = 0x00;                                        //清空当前计数值
  66.         SysTick->CTRL = 0x00000005;                                //设置时钟源为HCLK,启动定时器
  67.         while(!(SysTick->CTRL & 0x00010000));        //等待计数到0
  68.         SysTick->CTRL = 0x00000004;                                //关闭定时器
  69. }

  70. /**
  71.   * @brief  毫秒级延时
  72.   * @param  xms 延时时长,范围:0~4294967295
  73.   * @retval 无
  74.   */
  75. void Delay_ms(uint32_t xms)
  76. {
  77.         while(xms--)
  78.         {
  79.                 Delay_us(1000);
  80.         }
  81. }

  82. /**
  83.   * @brief  秒级延时
  84.   * @param  xs 延时时长,范围:0~4294967295
  85.   * @retval 无
  86.   */
  87. void Delay_s(uint32_t xs)
  88. {
  89.         while(xs--)
  90.         {
  91.                 Delay_ms(1000);
  92.         }
  93. }

  94. /***************************************************/主函数
  95. uint16_t key,light;

  96. int main(void)
  97. {
  98.         OLED_Init();
  99.         ADC_init();
  100.         OLED_ShowString(1,1,"Hello,my honey");
  101. //        OLED_ShowString(2,1,"Hello WangFang");
  102. //        OLED_ShowString(3,1,"Hello Tomorrow");
  103. //        OLED_ShowString(4,1,"I miss you");

  104.         while(1)
  105.         {
  106.                 key=get_adcvalue(ADC_Channel_0);
  107.                 light=get_adcvalue(ADC_Channel_1);
  108.                
  109.                 OLED_ShowNum(2,1,key,5);
  110.                 OLED_ShowNum(3,1,light,5);
  111.         }
  112. }


 楼主| t60yz 发表于 2023-11-22 12:03 | 显示全部楼层
3.DMA实现数据迁移
**1.结构原理
89404655d7d9c77a38.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部