打印
[其他ST产品]

STM8单片机ADC、Timer、USART实用例程

[复制链接]
287|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
两只袜子|  楼主 | 2023-8-3 15:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
AD, ADC, SAR, ST, STM
这是一个我花了较长时间摸索出来的STM8L-051的例程,它控制LED灯,Timer2定时100us进入中断,软件启动ADC,采样10 次后取平均,将结果通过UASART发送至PC机,在超级终端上显示的实用程序,因其内存极小,不能用printf等函数,因此对于想用这款资源极少的MCU的开发者来说,读这篇文章会大大节约你的研发时间。有不会的问题请发邮件



#include

#include "stm8l15x.h"

#include "iostm8l051f3.h"



#define LED_GPIO_PORT  GPIOA

#define LED_GPIO_PINS  GPIO_Pin_2 | GPIO_Pin_3



#define ADC1_DR_ADDRESS        ((uint16_t)0x5344)

#define BUFFER_SIZE            ((uint8_t) 0x02)

#define BUFFER_ADDRESS         ((uint16_t)(&Buffer))

#define ASCII_NUM_0            ((uint8_t)   48)

#define ADC_RATIO              ((uint16_t) 806)

#define SampleADC              ((uint8_t) 0x0A)   

uint8_t Buffer[4]  = {0, 0, 0, 0};

uint16_t ADCdata = 0;

uint16_t ADCvalue = 0;

unsigned char LED =1;

unsigned char c = 8;

uint16_t   acode = 1234; //43 "+" 0x2B;



void Delay(__IO uint16_t nCount)

{



  while (nCount != 0)

  {

    nCount--;

  }

}



//int putchar(int c)

//{

//  while ((USART1_SR&0x80)==0x00);

//  UART2_sendchar((u8)c);

//  return (c);

//}



static void CLK_Config(void)

{



  CLK_SYSCLKSourceSwitchCmd(ENABLE);

  CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);





  CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);



  while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_HSI)

  {}





  CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, ENABLE);





// CLK_PeripheralClockConfig(CLK_Peripheral_DMA1, ENABLE);





  CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, ENABLE);



  CLK_PeripheralClockConfig(CLK_Peripheral_USART1, ENABLE);

}



static void GPIO_Config(void)

{

  PC_DDR = 0X20;

  PC_CR1 = 0X20;

  PA_DDR = 0X0C;

  PA_CR1 = 0X0C;

}



static void USART1_Config(void)

{

// ADCvalue = USART1_DR;

  USART1_BRR2 = 0x03;

  USART1_BRR1 = 0x68;  //16M/9600=683

  USART1_CR2 = 0x0C;  //Transmitter & receiver enable

}



static void ADC_Config(void)

{

  ADC1_CR2 = 0x27; //risign edge, trigger 3, sampling time 384

  ADC1_CR3 = 0x10; //16channel

  //  ADC_ChannelCmd(ADC1, ADC_Channel_17, ENABLE);

}



void TIM2_Config(void)

{

  TIM2_PSCR = 0x07;  // 应是16,但只能置三位,所以是111  fCK_PSC / 2(PSC[2:0]).

  // TIM2_PSCRL = 0x3F;  // PSCR=0x1F3F,f=8M/(0x1F3F+1)=1000Hz,每个计数周期1ms

  TIM2_ARRH = 0x00;  // 自动重载寄存器ARR=0x01F4=500

  TIM2_ARRL = 0x18;  // 24X4us=96us   每记数500次产生一次中断,即500ms

  TIM2_IER = 0x01;   // 允许更新中断

  TIM2_CR1 = 0x05;   // 计数器使能,开始计数,只允许更新中断请求

}



void Delay (uint16_t nCount);



//#pragma   vector = ADC1_EOC_vector

//__interrupt  void  ADC1_EOC(void)

//{

//     ADCdata = ADC_GetConversionValue(ADC1);

// }



#pragma vector =TIM2_OVR_UIF_vector

__interrupt void TIM2_OVR_UIF(void)

{

    asm("sim");

    static uint8_t measurements = SampleADC;

    static uint32_t accumulator = 0;

    uint32_t average = 0;

    uint16_t factor10 = 1000;

    int8_t i ;

    ADCdata = 0;

    TIM2_SR1 = 0x00; //Clear UIF

    ADC1_SR = 0x00;  //Clear EOC

    ADC1_CR1 = 0x03; // EOC interrupt unable, software set start, ADC enable

  //  while (!(ADC1_SR & 0x01));





    Delay(0x000F);

    ADCdata = (uint16_t)(ADC1_DRH);

    ADCdata = (uint16_t)((uint16_t)((uint16_t)ADCdata << 8) | ADC1_DRL);

    accumulator += ADCdata;

    if(measurements == 0)

    {

        LED= !LED;

        measurements = SampleADC;

        average = accumulator/SampleADC;

        ADCvalue = (uint16_t)((uint32_t)((uint32_t)average * (uint32_t)ADC_RATIO) / (uint32_t)1000);

        accumulator = 0;

        while(!USART1_SR_TXE);

        for (i = 3; i >= 0; i--)

        {

           Buffer = (ADCvalue/factor10) % 10 + 48; //提取十进制每一位,并转换成ASCII码

           factor10 = factor10 / 10;

           while(!USART1_SR_TXE);

           USART1_DR = Buffer;  //发送每一位,先发高位

         }

        while(!USART1_SR_TXE);

        USART1_DR = 32;  //发送空格

     }

    measurements--;

    asm("rim");

}



void main(void)

{

   asm("sim");



   GPIO_Config();



   GPIO_Init(LED_GPIO_PORT, LED_GPIO_PINS, GPIO_Mode_Out_PP_Low_Fast);



   CLK_Config();



   ADC_Config();



   TIM2_Config();



   USART1_Config();



   //DMA_Config();



   asm("rim");



   while (1) {  

     PA_ODR_ODR2 = LED;

     PA_ODR_ODR3 = LED; }



}

使用特权

评论回复
沙发
中国龙芯CDX| | 2023-12-28 08:35 | 只看该作者
楼主这个是自己写的?感觉注释较少

使用特权

评论回复
板凳
童雨竹| | 2024-3-8 07:02 | 只看该作者

这些引线越窄越好

使用特权

评论回复
地板
Wordsworth| | 2024-3-8 08:05 | 只看该作者

图像由前景和背景组成,在灰度直方图上,前景和背景会形成高峰,在双峰之间的最低谷处就是阈值。

使用特权

评论回复
5
Clyde011| | 2024-3-8 09:08 | 只看该作者

要将多余空间去除。对于第一个字符从第一行开始向下扫描,把那些一行中所有的点的灰度值全为0的点去掉,直到扫描到有一行不全为0时为止。

使用特权

评论回复
6
公羊子丹| | 2024-3-8 10:01 | 只看该作者

输入滤波电容的公共端应作为其他交流电流地的唯一接点

使用特权

评论回复
7
万图| | 2024-3-8 11:04 | 只看该作者

根据色彩的变化记录每一行的颜色跳变点,由此识别出车牌区域。

使用特权

评论回复
8
Uriah| | 2024-3-8 12:07 | 只看该作者

切割完了第四个字符之后,再依次扫描剩下的空间,直到所扫描的这一竖上的所有点的灰度值不全为0时,认为是字符的开始并依次扫描直到所扫描的这一竖上的所有点的灰度值全为0时认为是字符的结束。

使用特权

评论回复
9
帛灿灿| | 2024-3-8 14:03 | 只看该作者

计算量小,计算快。缺点也严重:在不同的图像中,颜色分布差别大,处理效果也不会很好。

使用特权

评论回复
10
Bblythe| | 2024-3-8 15:06 | 只看该作者

在内存中开辟七个长为车牌长的七分之一和宽为车牌宽的区域

使用特权

评论回复
11
周半梅| | 2024-3-8 17:02 | 只看该作者

把纹波电流分摊到每个电容上

使用特权

评论回复
12
Pulitzer| | 2024-3-8 18:05 | 只看该作者

分别记录车牌区域的上下高度。然后通过RGB-HSV颜色转换

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2038

主题

7364

帖子

10

粉丝