基于STC8G1K17的信号转换方案

在昨天的博文 信号转换问题 | 模拟电路解决方式 中对于前天的 信号转换的解题思路 进行了实物仿真。尽快其中做了些改进,但是在控制二倍频的三角波的频率、幅值、占空比方面还是有很多的问题。主要表现在:

  • 控制量之间的耦合,特别是频率,占空比对输出信号幅值的影响;
  • 频率对于占空比的影响虽然经过改进之后,还是会有部分的影响;
  • 输出心慌可失真,这主要是最后一级从方波到三角波转换的过程中,对于信号的直流分量的变化与波形失真之间的关系;
  • 最后一点,也是最重要的一点,就是电路非常复杂。

那么,通过一个单片机是否可以完成同样的功能呢。

下面是选用的STC单片机来实现相同的功能。


01设计电路1

1.实验电路设计

▲ 实验原理图

▲ 实验原理图

▲ 实验电路板

▲ 实验电路板

2.单片机固件设置

使用STC的ISP软件对单片机进行硬件设置,设置IRC频率为35MHz。
▲ STC8G1K08单片机硬件设置

▲ STC8G1K08单片机硬件设置

下载基础程序之后的单片机开始能够工作。

▲ 下载固件之后的单片机

▲ 下载固件之后的单片机


02单片机程序设计2

1.设置PWM输出

STC8G1K 单片机的PWM输出可以有6,7,8,.10等不同的位数。在同样的系统时钟下,不同的位数对应的输出PWM的频率以及精度各不相同。

特别注意:需要在主程序中将PWM输出端口设置为推挽输出模式。

在35MHz下,6bit的PWM频率大约为540kHz。下面是通过510欧姆和0.1uF的电容对输出的PWM波形进行滤波,可以得到比较平滑的直流分量。

▲ 设置PWM输出6BIT

▲ 设置PWM输出6BIT

如果设置为8Bit,则输出PWM的波形的频率降低4倍,大约137kHz。通过10k欧姆、0.1uF的阻容滤波,所得到的直流分量可以看到有一些比较明显的波动了。

▲ PWM输出以及滤波后的直流信号 8BIT

▲ PWM输出以及滤波后的直流信号 8BIT

2.设置比较器

设置比较器,比较器结果通过CMPOE输出。

特别注意的是,需要明确在主程序中,将比较器的输出通过 PM_PP设置为推挽输出。

#if CMP_EN
void SetCMPPort(unsigned char ucPort) {
    if(ucPort           == CMP_P3) {
        ACC = P_SW2;
        ACC &= ~CMPO_S;
        P_SW2 = ACC;        
    } else if(ucPort    == CMP_P4) {
        ACC = P_SW2;
        ACC &= ~CMPO_S;
        ACC |= CMPO_S;
        P_SW2 = ACC;                
    }
}
void CMPInit(void) {
    CMPCR1 = 0x84;                          // CMPEN CMPIF PIE NIE PIS NIS CMPOE CMPRFESS
                                            // CMPEN:0: Disable Comparator; 1:Enable
                                            // CMPIF : Interrupt flag of comparator
                                            // PIE : 1 Enable Up edge interrupt
                                            // NIE : 1 Enable Down edge interrupt
                                            // PIS : 0 : +=P3.7; 1:=ADC_CHS
    CMPCR1 |= 0x2;                          // NIS : 0 : -=BandGap; 1 : P3.6
                                            // COMPOE : 1 : Result =P3.4,P4.1
                                            // Compare result.
    CMPCR1 |= 0x30;                         // Enable Up and Down Interrupt.
    CMPCR2 = 0x0;                           // INVCOMPO: 0 : Positive; 1 : Inverse output
                                            // DISFLT: 0 : Enable 0.1us analog filter
                                            // LCDTY: Digital Filter
}

▲ 比较器输出

▲ 比较器输出

在比较器中断中,测量半周期:

//------------------------------------------------------------------------------
#if CMP_INT_EN
void CMP_ISR(void) interrupt 21 {
    CMPCR1 &= ~0x40;                        // Clear the interrupt flag
    if(g_nSignalPeriodCount != g_nSignalPeriod) {
        g_nSignalPeriod = g_nSignalPeriodCount;
        if(g_nSignalPeriod > PWM_BUFFER) {
            g_nSignalPeriod = PWM_BUFFER;
        }
        g_ucSignalPeriodInitFlag = 1;
    }
    g_nSignalPeriodCount = 0;
    g_nSignalPWMBufferPoint = 0;
}
#endif // CMP_INT_EN

3. :初始化TImer0输出

//------------------------------------------------------------------------------
void InitSignalPWMBuffer(void) {
    unsigned int i;
    unsigned int nUpPeriod, nDownPeriod;
    unsigned long nMax;
    if(g_nSignalPeriod > PWM_BUFFER)
        g_nSignalPeriod = PWM_BUFFER;
    g_ucSignalPeriodInitFlag = 0;
    nMax = g_nSignalPeriod;
    nMax *= g_ucSignalPWMDuty;
    nMax /= 100;
    nUpPeriod = (unsigned int)nMax;
    nDownPeriod = g_nSignalPeriod - nUpPeriod;
    nMax = PWM_MAX;
    nMax = nMax * g_ucSignalPWMAmplitude;
    nMax /= 0xff;
    for(i = 0; i < nUpPeriod; i ++) {
        g_ucSignalPWMBuffer[i] = (unsigned char)(i * nMax / nUpPeriod);
    }
    for(i = 0; i < nDownPeriod; i ++) {
        g_ucSignalPWMBuffer[i + nUpPeriod] = (unsigned char)((nDownPeriod - i) * nMax / nDownPeriod);
    }       
}

▲ 测试输出波形

▲ 测试输出波形

▲ 占空比的改变

▲ 占空比的改变

▲ 改变幅值

▲ 改变幅值


03极限测试

  1. 三角波的占空比可以从0~100%,分成100个等级进行调节;
  2. 三角波的幅值从0~256,分成256个等级进行调剂
  3. 三角波的频率:5.556Hz

这是由于在单片机中进行波形数据区间长度为:buffer =9000
PWM DA输出是Timer0的中断,时间间隔为 ts=200us。
那么,三角波的周期最长为: buffer * ts = 0.18s。对应的频率为5.556Hz

▲ 频率过低的时候出现的波形断续

▲ 频率过低的时候出现的波形断续

  1. 三角波的最大频率: 250Hz

由于PWM DA输出的时间间隔为0.2ms,所以按照它它的20倍来估计三角波的最短周期为4ms,对应的频率为250Hz。

下面是对应的三角波的频率在300Hz是的波形,可以明显看出三角波的台阶。
▲ 三角波在300Hz是的波形

▲ 三角波在300Hz是的波形


04结论

通过前面的实验,可以验证,通过一个简单的单片机的电路,便可以完成对应的波形转换的功能。不仅简化了设计,同时也提高的波形转换的性能。

本文中所涉及到的硬软件文件可以从以下链接下载:

  1. 实验AD设计文件和C51程序

  1. AD工程文件:AD\Teaching\2020\SignalChange\Ver8G1K08.SchDoc ↩︎

  2. 单片机软件:C51\STC\Test\2020\Teach\Sin2Tri\Sin2TriSTC8G1K.uvproj ↩︎

好的,以下是一个基于 STC8G1K08A 的 ADC 采样电压的程序示例: ```c #include <STC8.H> #define ADC_CHANNEL 0 // ADC 采样通道为 CH0 #define ADC_CLOCK_DIV 0x0A // ADC 采样时钟分频为 10 void ADC_Init() { P1ASF = 1 << ADC_CHANNEL; // 将 ADC 通道 P1.0 对应的 P1ASF 寄存器位置 1 ADC_CON |= (0x80 | ADC_CLOCK_DIV | ADC_CHANNEL); // 设置 ADC 控制寄存器,启动 ADC 并设置采样时钟和采样通道 } unsigned int ADC_Read() { unsigned int adc_result = 0; ADC_CON |= 0x40; // 启动 ADC 转换 while (!(ADC_CON & 0x20)); // 等待 ADC 转换完成 adc_result = ADC_DATA_H << 2; // 读取 ADC 转换结果 adc_result |= ADC_DATA_L; return adc_result; } void main() { unsigned int adc_value = 0; ADC_Init(); // 初始化 ADC while (1) { adc_value = ADC_Read(); // 读取 ADC 转换结果 // 将 adc_value 转换为对应的电压值,具体转换方式需要根据参考电压和 ADC 分辨率进行计算 } } ``` 在上述程序中,我们首先定义了 ADC_CHANNEL 和 ADC_CLOCK_DIV 两个常量,分别表示 ADC 采样通道和采样时钟分频。在 ADC_Init() 函数中,我们将 P1.0 对应的 P1ASF 寄存器位置 1,以启用 ADC 通道 P1.0 的输入。然后我们设置 ADC_CON 寄存器,启动 ADC 并设置采样时钟和采样通道。ADC_Read() 函数中,我们启动 ADC 转换并等待转换完成,然后获取 ADC 转换结果,最后返回结果。在 main() 函数中,我们循环读取 ADC 转换结果,并将结果转换为对应的电压值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卓晴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值