打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
STM8学习笔记

STM8S003单片机ADC采样通道总共有5个,从AIN2---AIN6,多通道采样时需要将ADC转换设置为单次转换模式,每次切换采样通道后,需要重新初始化 ADC,采样结果在中断中读取。

IO口初始化代码

  1. //AD通道引脚初始化
  2. void ADC_GPIO_Init( void )
  3. {
  4. PD_DDR &= ~( 1 << 2 ); //PD2 设置为输入 AIN3
  5. PD_CR1 &= ~( 1 << 2 ); //PD2 设置为悬空输入
  6. PD_DDR &= ~( 1 << 3 ); //PD3 设置为输入 AIN4
  7. PD_CR1 &= ~( 1 << 3 ); //PD3 设置为悬空输入
  8. PC_DDR &= ~( 1 << 4 ); //PC4 设置为输入 AIN2
  9. PC_CR1 &= ~( 1 << 4 ); //PC4 设置为悬空输入
  10. PD_DDR &= ~( 1 << 5 ); //PD5 设置为输入 AIN5
  11. PD_CR1 &= ~( 1 << 5 ); //PD5 设置为悬空输入
  12. PD_DDR &= ~( 1 << 6 ); //PD6 设置为输入 AIN6
  13. PD_CR1 &= ~( 1 << 6 ); //PD6 设置为悬空输入
  14. }

将ADC的IO口都设置为输入模式,悬空输入。

下来初始化ADC功能

  1. void ADC_CH_Init( u8 ch )
  2. {
  3. char l = 0;
  4. ADC_CR1 = 0x00; //fADC = fMASTER/2, 8Mhz 单次转换,禁止转换
  5. ADC_CSR = ch + 1; //控制状态寄存器 选择要 AD输入通道 如:PD2(AIN3)
  6. ADC_CR2 = 0x00; //默认左对齐 读数据时先读高在读低
  7. ADC_TDRL = ( 1 << ( ch + 1 ) ); //禁止相应通道 施密特触发功能 1左移ch+1位
  8. ADC_CR1 |= 0x01; //使能ADC并开始转换
  9. ADC_CSR |= 0x20; //EOCIE 使能转换结束中断 EOC中断使能
  10. for( l = 0; l < 100; l++ ); //延时,保证ADC模块的上电完成 至少7us
  11. ADC_CR1 = ADC_CR1 | 0x01; //再次将CR1寄存器的最低位置1 使能ADC 并开始转换
  12. }

将ADC设置为单次转换模式,每次转换时需要手动将CR1寄存器最低位置1.

在中断中读取转换成功后的数据。

  1. #pragma vector = 24 // IAR中的中断号,要在STVD中的中断号上加2
  2. __interrupt void ADC_Handle( void )
  3. {
  4. ADC_CSR &= ~0x80; // 转换结束标志位清零 EOC
  5. //默认左对齐 读数据时先读高高8位 再读低8位
  6. DATAH = ADC_DRH; // 读出ADC结果的高8位
  7. DATAL = ADC_DRL; // 读出ADC结果的低8位
  8. ADC_flag = 1; // ADC中断标志 置1
  9. }

中断中将转换后的采样值存储在DATAH,和DATAL中,并置位采样结束标志位ADC_flag,采样函数判断标志位为1时,就去读取ADC采样值。

采样值读取函数:

  1. //采集PC4电压值 AIN2
  2. u16 ReadVol_CH2( void )
  3. {
  4. u16 voltage = 0;
  5. ADC_CH_Init( 1 );
  6. while( ADC_flag == 0 );
  7. if( ADC_flag )
  8. {
  9. ADC_flag = 0;
  10. voltage = ( DATAH << 2 ) + DATAL ; //得到十位精度的数据 0--1024
  11. //ADC_CR1 = ADC_CR1 | 0x01; // 再次将CR1寄存器的最低位置1 启动下一次转换
  12. };
  13. return voltage;
  14. }

单片机有些引脚的功能需要通过选项字开启,通过ST Visual Programmer软件设置选项字方法如下:

在AFR7中,将选项字中将PC4设置为AIN2功能。

adc完整代码如下:

  1. #include "adc.h"
  2. #include "main.h"
  3. u16 DATAH = 0; //ADC转换值高8位
  4. u16 DATAL = 0; //ADC转换值低8位
  5. _Bool ADC_flag = 0; //ADC转换成功标志
  6. //AD通道引脚初始化
  7. void ADC_GPIO_Init( void )
  8. {
  9. PD_DDR &= ~( 1 << 2 ); //PD2 设置为输入 AIN3
  10. PD_CR1 &= ~( 1 << 2 ); //PD2 设置为悬空输入
  11. PD_DDR &= ~( 1 << 3 ); //PD3 设置为输入 AIN4
  12. PD_CR1 &= ~( 1 << 3 ); //PD3 设置为悬空输入
  13. PC_DDR &= ~( 1 << 4 ); //PC4 设置为输入 AIN2
  14. PC_CR1 &= ~( 1 << 4 ); //PC4 设置为悬空输入
  15. PD_DDR &= ~( 1 << 5 ); //PD5 设置为输入 AIN5
  16. PD_CR1 &= ~( 1 << 5 ); //PD5 设置为悬空输入
  17. PD_DDR &= ~( 1 << 6 ); //PD6 设置为输入 AIN6
  18. PD_CR1 &= ~( 1 << 6 ); //PD6 设置为悬空输入
  19. }
  20. //ADC输入通道初始化入口参数表示通道选择
  21. void ADC_CH_Init( u8 ch )
  22. {
  23. char l = 0;
  24. ADC_CR1 = 0x00; //fADC = fMASTER/2, 8Mhz 单次转换,禁止转换
  25. ADC_CSR = ch + 1; //控制状态寄存器 选择要 AD输入通道 如:PD2(AIN3)
  26. ADC_CR2 = 0x00; //默认左对齐 读数据时先读高在读低
  27. ADC_TDRL = ( 1 << ( ch + 1 ) ); //禁止相应通道 施密特触发功能 1左移ch+1位
  28. ADC_CR1 |= 0x01; //使能ADC并开始转换
  29. ADC_CSR |= 0x20; //EOCIE 使能转换结束中断 EOC中断使能
  30. for( l = 0; l < 100; l++ ); //延时,保证ADC模块的上电完成 至少7us
  31. ADC_CR1 = ADC_CR1 | 0x01; //再次将CR1寄存器的最低位置1 使能ADC 并开始转换
  32. }
  33. //采集PC4电压值 AIN2
  34. u16 ReadVol_CH2( void )
  35. {
  36. u16 voltage = 0;
  37. ADC_CH_Init( 1 );
  38. while( ADC_flag == 0 );
  39. if( ADC_flag )
  40. {
  41. ADC_flag = 0;
  42. voltage = ( DATAH << 2 ) + DATAL ; //得到十位精度的数据 0--1024
  43. //ADC_CR1 = ADC_CR1 | 0x01; // 再次将CR1寄存器的最低位置1 启动下一次转换
  44. };
  45. return voltage;
  46. }
  47. //采集PD2电压值 AIN3
  48. u16 ReadVol_CH3( void )
  49. {
  50. u16 voltage = 0;
  51. ADC_CH_Init( 2 );
  52. while( ADC_flag == 0 );
  53. if( ADC_flag )
  54. {
  55. ADC_flag = 0;
  56. voltage = ( DATAH << 2 ) + DATAL ;
  57. //ADC_CR1 = ADC_CR1 | 0x01; //当通道不需要切换时,只需初始化一次,以后每次读取完数据后,需要手动开启下一次转换
  58. };
  59. return voltage;
  60. }
  61. //采集PD3电压值 AIN4
  62. u16 ReadVol_CH4( void )
  63. {
  64. u16 voltage = 0;
  65. ADC_CH_Init( 3 );
  66. while( ADC_flag == 0 );
  67. if( ADC_flag )
  68. {
  69. ADC_flag = 0;
  70. voltage = ( DATAH << 2 ) + DATAL ; //得到十位精度的数据 0--1024
  71. //ADC_CR1 = ADC_CR1 | 0x01; // 再次将CR1寄存器的最低位置1 启动下一次转换
  72. };
  73. return voltage;
  74. }
  75. //采集PD5电压值 AIN5
  76. u16 ReadVol_CH5( void )
  77. {
  78. u16 voltage = 0;
  79. ADC_CH_Init( 4 );
  80. if( ADC_flag )
  81. {
  82. ADC_flag = 0;
  83. voltage = ( DATAH << 2 ) + DATAL ; //得到十位精度的数据 0--1024
  84. //ADC_CR1 = ADC_CR1 | 0x01; //再次将CR1寄存器的最低位置1 启动下一次转换
  85. };
  86. return voltage;
  87. }
  88. //采集PD6电压值 AIN6
  89. u16 ReadVol_CH6( void )
  90. {
  91. u16 voltage = 0;
  92. ADC_CH_Init( 5 );
  93. if( ADC_flag )
  94. {
  95. ADC_flag = 0;
  96. voltage = ( DATAH << 2 ) + DATAL ; //得到十位精度的数据 0--1024
  97. //ADC_CR1 = ADC_CR1 | 0x01; //再次将CR1寄存器的最低位置1 启动下一次转换
  98. };
  99. return voltage;
  100. }
  101. //AD中断服务函数 中断号22
  102. #pragma vector = 24 // IAR中的中断号,要在STVD中的中断号上加2
  103. __interrupt void ADC_Handle( void )
  104. {
  105. ADC_CSR &= ~0x80; // 转换结束标志位清零 EOC
  106. //默认左对齐 读数据时先读高高8位 再读低8位
  107. DATAH = ADC_DRH; // 读出ADC结果的高8位
  108. DATAL = ADC_DRL; // 读出ADC结果的低8位
  109. ADC_flag = 1; // ADC中断标志 置1
  110. }

 

主函数代码如下:

  1. #include "iostm8s103F3.h"
  2. #include "main.h"
  3. #include "led.h"
  4. #include "adc.h"
  5. #include "delay.h"
  6. u16 val_ch2 = 0, val_ch3 = 0, val_ch4 = 0, val_ch5 = 0, val_ch6 = 0;
  7. void SysClkInit( void )
  8. {
  9. CLK_SWR = 0xe1; //HSI为主时钟源 16MHz CPU时钟频率
  10. CLK_CKDIVR = 0x00; //CPU时钟0分频,系统时钟0分频
  11. }
  12. void main( void )
  13. {
  14. u8 i=0;
  15. __asm( "sim" ); //禁止中断
  16. SysClkInit();
  17. delay_init( 16 );
  18. LED_GPIO_Init();
  19. ADC_GPIO_Init();
  20. __asm( "rim" ); //开启中断
  21. while( 1 )
  22. {
  23. LED = ~LED;
  24. //通道切换后,采样的第一笔数据仍然为上一通道的数据
  25. for(i=0;i<10;i++)
  26. val_ch2 = ReadVol_CH2();
  27. delay_ms( 100 );
  28. for(i=0;i<10;i++)
  29. val_ch3 = ReadVol_CH3();
  30. delay_ms( 100 );
  31. for(i=0;i<10;i++)
  32. val_ch4 = ReadVol_CH4();
  33. delay_ms( 100 );
  34. for(i=0;i<10;i++)
  35. val_ch5 = ReadVol_CH5();
  36. delay_ms( 100 );
  37. for(i=0;i<10;i++)
  38. val_ch6 = ReadVol_CH6();
  39. delay_ms( 100 );
  40. }
  41. }

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
stm32 AD模数转换[操作寄存器+库函数]-Changing's Blog
STM8S各个模块初始化
AVR模拟比较器范例
利用MSP430内部DAC产生正弦信号
【转】IAR+STM8
STM32测试程序 ADC+DMA+串口发送。全代码奉献(操作寄存器)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服