STC12C2052AD AD conversion C program + PWM output function realization

Function: The STC12C2052AD microcontroller successfully implements an ADC conversion C program along with PWM output functionality.

Application: It is used for voltage detection, overvoltage protection (via relay control), and converting DC voltage into pulsating DC using PWM chopping.

Board Function: This board is designed to charge a phone battery.

For the LM317 buck converter, a small current application should be sufficient. Since there was no time to purchase a switch transistor, a 9013 transistor was used instead.

Drawing:

STC12C2052AD AD conversion C program + PWM output function realization

//The following is a successful program. If you need to apply it to your own project, you only need to change the IO pins accordingly.

//Full version of the program download address:

#include //Special header file for STC microcontroller

#include

#define uchar unsigned char

#define uint unsigned int

#define AD_SPEED 0x60 //0110,0000 - 270 clock cycles for conversion

/************ Hebei is waiting for you! &&&& less fish welcome you! ******************************/

//

sbit M = P1^5; //Overvoltage indicator

sbit N = P1^3; //Undervoltage indicator

sbit LED = P1^7; //Working status indicator

sbit CONTRL = P3^4; //Output control

sbit PWM = P3^7;

/************************************************* ***************/

void pwm();

void delayms(uint);

uint ADC();

void InitADC();

void baohu();

float voltage = 0.0;

uint V;

float VCC = 5.05;

uchar mtab[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

/***8********************************************* *****************/

void main()

{

CONTRL = 0; //First close the output

delayms(700);

V = 40; //These are added when I made a mistake. The purpose is to figure out exactly what AD has converted.

voltage = 4.0; //Practical proof, the replacement value is useless, indicating no AD

LED = 0;

CONTRL = 1;

voltage = V * VCC / 256.00 * 5.00;

delayms(1000);

PWM = 1;

CONTRL = 1; //Relay is working, in protection mode

delayms(1000);

M = 0;

N = 0;

LED = 0;

delayms(2000);

M = 1;

N = 1;

LED = 1;

pwm(); //Generate PWM waveform

delayms(7000);

delayms(100); //Delay

InitADC();

delayms(20);

V = ADC();

baohu();

while(1)

{

V = ADC();

baohu();

delayms(300);

}

}

//

//

void pwm()

{

//PCA module works in PWM mode

CMOD = 0x04; //Use timer 0 overflow for PCA pulse

CL = 0x00; //PCA timer low 8 bits (Address: E9H)

CH = 0x00; //PCA high 8-bit address (F9H)

CCON = 0x00;

CCAP0L = 0x60; //Control duty cycle in PWM mode

CCAP0H = 0x60; //0xff-0xc0=0x3f, 64/256=25% duty cycle (overflow)

CCAPM0 = 0x42; //Set PCA module 0 to PWM mode

//ECOM0=1 enable compare, PWM0=1 enable CEX0 pin as pulse width adjustment output

/*********************

PCA module working mode setting (CCAPMn register, n = 0-3)

7 6 5 4 3 2 1 0

- ECOMn CAPPn CAPNn MATn TOGn PWMn ECCFn

Options: 0x00 no action

0x20 16-bit capture mode, triggered by CEXn rising edge

0x10 16-bit capture mode, triggered by CEXn falling edge

0x30 16-bit capture mode, triggered by CEXn transition

0x48 16-bit software timer

0x4c 16-bit high speed output

0x42 8-bit PWM output

Each PCA module has two registers: CCAPnH and CCAPnL. They store 16-bit count values used for capturing or comparing, and control the duty cycle when operating in PWM mode.

*******************************/

TMOD = 0x02;

TH0 = 0x06;

TL0 = 0x06;

CR = 1; //Start PCA Timer

TR0 = 1;

}

//ADC conversion initialization - turn on ADC power supply

void InitADC()

{

P1 = 0xff;

ADC_CONTR |= 0x80;

delayms(80);

//These two registers are used to set the four states of the P1 port, each bit corresponds to a P1 pin, combined operation based on state

/*****************

P1M0 and P1M1 register bits 7 6 5 4 3 2 1 0

P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0

The same applies to P3M0 and P3M1. Since the STC12C2052AD only has two P ports, there are only two groups of P1M0 and P1M1. For other models like STC12C5410AD, there are three groups.

P1M0 and P1M1 high

0 0 Normal I/O port (quasi-bidirectional)

0 1 Strong push-pull output (20mA current)

1 0 Input mode available for A/D conversion

1 1 Open drain, available for A/D conversion

Example:

To set P1.2 as an AD input port:

P1M0 = 0x02;

P1M1 = 0x02; //Open drain

When not using ADC, it's best to turn off the ADC power and restore to the I/O port state.

********************************/

P1M0 = 0x02; //Set P1.1 to open drain state

P1M1 = 0x02;

}

//ADC conversion program

/************************************************* *****

Note: The commands commented in this function are general commands that can be used for all AD channels. I have identified a specific channel (P1.1), so I directly assigned it to save "flow". The problem I encountered was the while loop in this function.

While (1) //Wait for the end of the A/D conversion

{

If (ADC_CONTR & 0x10) //Test if A/D conversion is complete

{ break; }

}

This works, but what I originally wrote was:

While (ADC_CONTR & 0x10 == 0);

This is incorrect because the precedence of '==' is higher than '&'.

So add brackets:

While ((ADC_CONTR & 0x10) == 0);

If you're not familiar with C, you might forget this!

A lesson learned from this: small problems can affect efficiency.

Experience: Adding brackets often helps avoid issues without consuming "flow"!

*********************************************/

uint ADC()

{

ADC_DATA = 0; //Clear result

ADC_CONTR = 0x60; //Set conversion speed to fastest

ADC_CONTR = 0xE0; //Clear ADC_FLAG, ADC_START bit, and lower 3 bits

ADC_CONTR = 0xe1;

//ADC_CONTR |= 0x01; //Select A/D channel P1.1

delayms(1); //Stabilize input voltage

ADC_CONTR = 0xe9;

//ADC_CONTR |= 0x08; //Start A/D conversion

While (1) //Wait for A/D conversion to finish

{

If (ADC_CONTR & 0x10) //Check if A/D conversion is done

{ break; }

}

ADC_CONTR = 0xe1;

//ADC_CONTR &= 0xE7; //Clear ADC_FLAG, disable A/D conversion

return ADC_DATA; //Return 10-bit A/D conversion result

}

//

void baohu()

{

voltage = V * VCC / 256.00 * 5.00;

if(voltage > 5.25)

{

CONTRL = 1; //Overvoltage protection, turn off the switch tube control

M = 0;

N = 1;

LED = 1;

}

if(voltage < 4.62 && voltage > 4.50)

Silicone rubble cold shrinkable tube

Dongguan Zhonghe Electronics Co., Ltd. , https://www.zhonghesleeving.com