chun1234
发表于 2024-8-30 16:15:13
本帖最后由 chun1234 于 2024-8-30 16:28 编辑
学习冲哥的《STC32G单片机视频教程》 第十七课 模数转换器ADC
一、模数转换器是什么:模数转换器即A/D转换器,通常是指一个将模拟信号转变为数字信号的电子元件。STC32G系列单片机内部集成了一个12位高速A/D转换器。ADC的时钟频率为系统频率2分频再经过用户设置的分频系数进行再次分频。ADC转换结果的数据格式有两种:左对齐和右对齐,可方便用户进行读取和引用。冲哥在这里引用了一段裁切木板的视频来讲解如何形成的二进制转换结果,很直观,易懂易用。 注意:使用ADC功能时有Vref引脚的单片机,千万千万不能悬空,必须接外部参考电压源或者VCC!
二、STC32G单片机ADC使用原理:1、ADC控制寄存器共有5个位:ADC_POWER ADC电源控制位ADC_START ADC转换启动控制位ADC_FLAGADC转换结束标志位ADC_CHSADC模拟通道选择位ADC_EPWMT 使能PWM实时触发ADC功能
2、ADC转换结果计算公式:3、高精度ADC采集 参考电路图:
三、编写最简单的ADC采集代码:
#include "COMM/stc.h" //调用头文件
#include "COMM/usb.h"
#include "seg_led.h"
#include "key.h"
#include "beep.h"
#include "tim0.h"
#include "exit.h"
#include "adc.h"
#define MAIN_Fosc 24000000UL //定义主时钟
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
bitTIM_10MS_Flag; //10ms的标志位
u16 Tme_CountDown = 0; //全局变量
void sys_init(); //函数声明
void delay_ms(u16 ms); //unsigned int
void main() //程序开始运行的入口
{
sys_init(); //USB功能+IO口初始化
usb_init(); //usb库初始化
Timer0_Init(); //定时器0初始化
ADC_Init();
EA = 1; //CPU开放中断,打开总中断。
while(1) //死循环
{
delay_ms(2);
if( DeviceState != DEVSTATE_CONFIGURED ) //
continue;
if( bUsbOutReady )
{
usb_OUT_done();
}
if( TIM_10MS_Flag==1 ) //如果10ms到了
{
TIM_10MS_Flag = 0; //清空标志位
//ADC_Read(0); //读取DC的数值
printf("当前ADC数\xfd值:%d\t%dmv\r\n",(int)adc_val,(int)ADC_CAL_Voltage(adc_val)); //串口打印ADC数值
}
}
}
void Timer0_Isr(void) interrupt 1
{
static timcount = 0;
SEG_LED_Show(); //数码管刷新的
timcount++; //1ms+1
if( timcount>=10 ) //如果这个变量大于等于10,10ms计数到达
{
timcount = 0;
TIM_10MS_Flag = 1; //10ms时间到了
}
}
void sys_init() //函数定义
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P3M0 = 0x00;
P3M1 = 0x00;
P3M0 &= ~0x03;
P3M1 |= 0x03;
//设置USB使用的时钟源
IRC48MCR = 0x80; //使能内部48M高速IRC
while (!(IRC48MCR & 0x01));//等待时钟稳定
USBCLK = 0x00; //使用CDC功能需要使用这两行,HID功能禁用这两行。
USBCON = 0x90;
}
void delay_ms(u16 ms) //unsigned int
{
u16 i;
do
{
i = MAIN_Fosc/6000;
while(--i);
}while(--ms);
}
以上代码已经验证通过。
chun1234
发表于 2024-9-4 14:33:50
本帖最后由 chun1234 于 2024-9-4 14:37 编辑
学习冲哥的《STC32G单片机视频教程》 第十八课 ADC采集电源电压和ADC按键
一、ADC反推电源电压1、测量出Vref引脚电压的意义?
由公式得知:我们需要知道Vref的电压才能换算出引脚上的输入电压!但是我们做小仪表的时候很多都是直接电池供电,锂电池电压3.7-4.3V,有时还会去掉基准电压电路和稳压电路。所以首先换算出Vref的引脚电压至关重要。 尽管电池电压不是稳定的,那我们只要测出某一个时刻的Vref引脚电压,可以多测几次,开头几次不要,只取稳定以后的Vref引脚电压即可。
2、具体实现过程请看以下代码: #include "COMM/stc.h" //调用头文件
#include "COMM/usb.h"
#include "seg_led.h"
#include "key.h"
#include "beep.h"
#include "tim0.h"
#include "exit.h"
#include "adc.h"
#define MAIN_Fosc 24000000UL //定义主时钟
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
bitTIM_10MS_Flag; //10ms的标志位
u16 Tme_CountDown = 0; //全局变量
bit RUN_STATE = 0; //0:正常运行1:参数设置
u8 S_HOUR = 0;
u8 S_MINUTE = 0;
u8 S_SECOND = 0;
void sys_init(); //函数声明
void delay_ms(u16 ms); //unsigned int
void TIME_SET_Second(void)
{
S_SECOND ++;
if( S_SECOND>60 )
{
S_SECOND = 0;
S_MINUTE++;
}
}
void main() //程序开始运行的入口
{
u16 VREF_VAL;
u16 count;
u8 keynum;
sys_init(); //USB功能+IO口初始化
usb_init(); //usb库初始化
delay_ms(500);
Timer0_Init(); //定时器0初始化
// ADC_Init();
VREF_VAL = ADC_VrefCal();//adc初始化+电源电压读取
EA = 1; //CPU开放中断,打开总中断。
while(1) //死循环
{
delay_ms(2);
if( DeviceState != DEVSTATE_CONFIGURED ) //
continue;
if( bUsbOutReady )
{
usb_OUT_done();
}
if( TIM_10MS_Flag==1 ) //如果10ms到了
{
TIM_10MS_Flag = 0; //清空标志位
Clock_InitShow(S_HOUR,S_MINUTE,S_SECOND); //刷新数码管的数值
BEEP_RUN();
if( RUN_STATE == 0) //正常运行
{
count++;
if( count==100 ) //计数到达10ms*100的时候执行一次
{
count=0;
TIME_SET_Second();
if(( S_HOUR==0 ) && ( S_MINUTE==0 ) && ( S_SECOND==30 )) // 时间到达00 - 00 - 30的时候
{
BEEP_ON(300);
}
}
}
keynum = ADC_KeyRead(ADC_Read(0));
switch( keynum )
{
case 11+0X80:
RUN_STATE=1;blink_bit = 0;
break; //按钮A长按,
case 12+0X80:
if( RUN_STATE==1 )
{
blink = 0;
Time_Count = 0;
TIME_SET_Second();
}
break; //按钮B长按,
case 14:
if( RUN_STATE==1 )
{
RUN_STATE = 0;
blink_bit = 0xff;
}
break; //按钮B长按,
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10: //如果是0-9的按钮按下
Show_Tab = (keynum-1);
blink_bit++; //闪烁的位换到下一个
if(( blink_bit==2 )||( blink_bit==5))
blink_bit++;
if( blink_bit == 8 )
{
RUN_STATE = 0;
}
S_HOUR = Show_Tab*10+Show_Tab;
S_MINUTE = Show_Tab*10+Show_Tab;
S_SECOND = Show_Tab*10+Show_Tab;
break;
}
}
}
}
void Timer0_Isr(void) interrupt 1
{
static timcount = 0;
SEG_LED_Show(); //数码管刷新的
timcount++; //1ms+1
if( timcount>=10 ) //如果这个变量大于等于10,10ms计数到达
{
timcount = 0;
TIM_10MS_Flag = 1; //10ms时间到了
}
}
void sys_init() //函数定义
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P3M0 = 0x00;
P3M1 = 0x00;
P3M0 &= ~0x03;
P3M1 |= 0x03;
//设置USB使用的时钟源
IRC48MCR = 0x80; //使能内部48M高速IRC
while (!(IRC48MCR & 0x01));//等待时钟稳定
USBCLK = 0x00; //使用CDC功能需要使用这两行,HID功能禁用这两行。
USBCON = 0x90;
}
void delay_ms(u16 ms) //unsigned int
{
u16 i;
do
{
i = MAIN_Fosc/6000;
while(--i);
}while(--ms);
}
二、ADC按键扫描(长按循环触发)
读ADC键方法:每隔10ms左右读取一次ADC值,并且保存最后3次的读数,其变化比较小时再判断键,判断键有效时,允许一定的偏差,比如正负16个字的偏差。
按键扫描原理图如下:
fztyp
发表于 2024-9-7 01:02:56
一起学习{:4_250:}{:4_174:}
chun1234
发表于 2024-9-12 09:14:06
本帖最后由 chun1234 于 2024-9-12 09:16 编辑
学习冲哥的《STC32G单片机视频教程》 第十九课 NTC温度采集
一、NTC的原理
1、NTC是指随温度上升电阻呈指数关系减小,具有负温度系数的热敏电阻材料和现象。NTC器件的种类常见有贴片型、直插型和金属头型。NTC的用途非常广泛。
用公式表示如下:
Rt = RT0*EXP(Bn*(1/T-1/T0))式中RT、RT0分别为温度为T、T0时的电阻值,Bn为材料常数,陶瓷晶粒本身由于温度变化而使电阻率发生变化,这是由半导体特性决定的。
2、NTC测温原理图:
二、NTC测温程序的编写#include "COMM/stc.h" //调用头文件
#include "COMM/usb.h"
#include "seg_led.h"
#include "key.h"
#include "beep.h"
#include "tim0.h"
#include "exit.h"
#include "adc.h"
#include "ntc.h"
#define MAIN_Fosc 24000000UL //定义主时钟
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
bitTIM_10MS_Flag; //10ms的标志位
u16 Tme_CountDown = 0; //全局变量
bit RUN_STATE = 0; //0:正常运行1:参数设置
u8 S_HOUR = 0;
u8 S_MINUTE = 0;
u8 S_SECOND = 0;
void sys_init(); //函数声明
void delay_ms(u16 ms); //unsigned int
void TIME_SET_Second(void)
{
S_SECOND ++;
if( S_SECOND>60 )
{
S_SECOND = 0;
S_MINUTE++;
}
}
void main() //程序开始运行的入口
{
int TEMP_VAL;
int count = 0;
sys_init(); //USB功能+IO口初始化
usb_init(); //usb库初始化
delay_ms(500);
Timer0_Init(); //定时器0初始化
ADC_Init();
P1M0 = 0x00; P1M1 = 0x08;
EA = 1; //CPU开放中断,打开总中断。
while(1) //死循环
{
delay_ms(2);
if( DeviceState != DEVSTATE_CONFIGURED ) //
continue;
if( bUsbOutReady )
{
usb_OUT_done();
printf("当前温度:%d\r\n",TEMP_VAL);
}
if( TIM_10MS_Flag==1 ) //如果10ms到了
{
TIM_10MS_Flag = 0; //清空标志位
count++;
if( count>=30 )
{
count = 0;
TEMP_VAL = Temp_Cal(ADC_Read(3));
SEG0 = TEMP_VAL/1000%10;
SEG1 = TEMP_VAL/100%10;
SEG2 = TEMP_VAL/10%10 +10;
SEG3 = TEMP_VAL/1%10;
}
}
}
}
void Timer0_Isr(void) interrupt 1
{
static timcount = 0;
SEG_LED_Show(); //数码管刷新的
timcount++; //1ms+1
if( timcount>=10 ) //如果这个变量大于等于10,10ms计数到达
{
timcount = 0;
TIM_10MS_Flag = 1; //10ms时间到了
}
}
void sys_init() //函数定义
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P3M0 = 0x00;
P3M1 = 0x00;
P3M0 &= ~0x03;
P3M1 |= 0x03;
//设置USB使用的时钟源
IRC48MCR = 0x80; //使能内部48M高速IRC
while (!(IRC48MCR & 0x01));//等待时钟稳定
USBCLK = 0x00; //使用CDC功能需要使用这两行,HID功能禁用这两行。
USBCON = 0x90;
}
void delay_ms(u16 ms) //unsigned int
{
u16 i;
do
{
i = MAIN_Fosc/6000;
while(--i);
}while(--ms);
}
chun1234
发表于 2024-9-20 17:04:56
本帖最后由 chun1234 于 2024-9-20 17:08 编辑
学习冲哥的《STC32G单片机视频教程》 第20课 串口通信
一、串口通信的基础知识
1、什么是通信每次发送一位数据的称为串行通信,多为一起传输的称为并行通信。而串口通信是串行通信中的一种。串口通信,是指外设和计算机间,通过数据信号线、地线、控制线等,安慰进行传输数据的一种通讯方式。这种通讯方式使用的数据线少,在远距离通信中可以节约通信成本,但是其传输速度比并行传输低。2、同步与异步 同步: ①同步是指以字符为单位传送信息; ②相邻两个字符间的间隔是任意长; ③因为一个字符中的比特位长度有限,所以需要的接收时钟和发送时钟只要相近就可以; ④同步方式特点简单说就是:字符间异步,字符内部各位同步。
异步:①以数据块为单位传输信息;②在一个数据块(信息帧)内,字符与字符间无间隔;③因为一次传输的数据块中包含的数据较多,所以接收时钟与发送时钟严格同步,通常要有同步时钟。
全双工:因为发送方与接收方都有单独的发送器和接收器,所以它们在传输数据时可以做到全双工工作。
波特率:例如9600的波特率意味着每秒钟可以发9600位的数据。
二、STC32的串口通信实现原理
1、引脚选择:串口1、串口2的通讯口均可以通过功能管脚切换功能切换到多组端口,从而可以将一个通讯口分时复用为多个通讯口。 2、模式选择:当PCON寄存器中的SM0的D0位为0时,该位和SM1一起指定串口1的通信工作模式。
图:串口1工作模式
三、串口通信代码的实现
#include "COMM/stc.h" //调用头文件
#include "COMM/usb.h"
#include "seg_led.h"
#include "key.h"
#include "beep.h"
#include "tim0.h"
#include "exit.h"
#include "adc.h"
#include "ntc.h"
#include "usart2.h"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
bitTIM_10MS_Flag; //10ms的标志位
u16 Tme_CountDown = 0; //全局变量
bit RUN_STATE = 0; //0:正常运行1:参数设置
u8 S_HOUR = 0;
u8 S_MINUTE = 0;
u8 S_SECOND = 0;
void sys_init(); //函数声明
void delay_ms(u16 ms); //unsigned int
void TIME_SET_Second(void)
{
S_SECOND ++;
if( S_SECOND>60 )
{
S_SECOND = 0;
S_MINUTE++;
}
}
void main() //程序开始运行的入口
{
sys_init(); //USB功能+IO口初始化
usb_init(); //usb库初始化
delay_ms(500);
Timer0_Init(); //定时器0初始化
Usart2_Init();
IE2 = 0X01;
EA = 1; //CPU开放中断,打开总中断。
Usart2_SendStr("USART2 TEST\r\n");
while(1) //死循环
{
// delay_ms(2);
// if( DeviceState != DEVSTATE_CONFIGURED ) //
// continue;
// if( bUsbOutReady )
// {
// usb_OUT_done();
// }
if( TIM_10MS_Flag==1 ) //如果10ms到了
{
TIM_10MS_Flag = 0; //清空标志位
}
if( rptr != wptr )
{
Usart2_Send(buffer);
rptr &= 0x0f;
}
}
}
void Timer0_Isr(void) interrupt 1
{
static timcount = 0;
SEG_LED_Show(); //数码管刷新的
timcount++; //1ms+1
if( timcount>=10 ) //如果这个变量大于等于10,10ms计数到达
{
timcount = 0;
TIM_10MS_Flag = 1; //10ms时间到了
}
}
void sys_init() //函数定义
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P3M0 = 0x00;
P3M1 = 0x00;
P3M0 &= ~0x03;
P3M1 |= 0x03;
//设置USB使用的时钟源
IRC48MCR = 0x80; //使能内部48M高速IRC
while (!(IRC48MCR & 0x01));//等待时钟稳定
USBCLK = 0x00; //使用CDC功能需要使用这两行,HID功能禁用这两行。
USBCON = 0x90;
}
void delay_ms(u16 ms) //unsigned int
{
u16 i;
do
{
i = MAIN_Fosc/6000;
while(--i);
}while(--ms);
}
chun1234
发表于 2024-9-26 10:56:49
本帖最后由 chun1234 于 2024-9-26 11:00 编辑
学习冲哥的《STC32G单片机视频教程》 第21课 串口应用
一、串口与PC通信的接线 TX和RX代表一组串口,TXDn和RXDn 表示这是第几组串口。 芯片与芯片之间的通信:如果通信协议和电平都一样,直接把TX和RX连接就可以通信。 串口与电脑USB通信:可以借助USB转TTL的工具进行连接。 推荐试用STC公司出品的USB转双串口工具(一箭双雕)进行连接,更方便连接下载与调试。
ISP下载步骤: 1、按照如图所示的连接方式,将USB转串口工具和目标芯片连接 2、点击 STC-ISP 下载软件中的“下载/编程” 按钮 3、开始ISP下载
二、利用实验箱示例代码移植驱动程序#include "COMM/stc.h" //调用头文件
#include "COMM/usb.h"
#include "seg_led.h"
#include "key.h"
#include "beep.h"
#include "tim0.h"
#include "exit.h"
#include "adc.h"
#include "ntc.h"
#include "usart2.h"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
bitTIM_10MS_Flag; //10ms的标志位
u16 Tme_CountDown = 0; //全局变量
bit RUN_STATE = 0; //0:正常运行1:参数设置
u8 S_HOUR = 0;
u8 S_MINUTE = 0;
u8 S_SECOND = 0;
void sys_init(); //函数声明
void delay_ms(u16 ms); //unsigned int
void TIME_SET_Second(void)
{
S_SECOND ++;
if( S_SECOND>60 )
{
S_SECOND = 0;
S_MINUTE++;
}
}
void main() //程序开始运行的入口
{
sys_init(); //USB功能+IO口初始化
usb_init(); //usb库初始化
delay_ms(500);
Timer0_Init(); //定时器0初始化
Usart2_Init();
IE2 = 0X01;
EA = 1; //CPU开放中断,打开总中断。
Usart2_SendStr("USART2 TEST\r\n");
while(1) //死循环
{
if( TIM_10MS_Flag==1 ) //如果10ms到了
{
TIM_10MS_Flag = 0; //清空标志位
}
if( rptr != wptr )
{
Usart2_Send(buffer);
rptr &= 0x0f;
}
}
}
void Timer0_Isr(void) interrupt 1
{
static timcount = 0;
SEG_LED_Show(); //数码管刷新
timcount++; //1ms+1
if( timcount>=10 ) //如果这个变量大于等于10,10ms计数到达
{
timcount = 0;
TIM_10MS_Flag = 1; //10ms时间到了
}
}
void sys_init() //函数定义
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P3M0 = 0x00;
P3M1 = 0x00;
P3M0 &= ~0x03;
P3M1 |= 0x03;
//设置USB使用的时钟源
IRC48MCR = 0x80; //使能内部48M高速IRC
while (!(IRC48MCR & 0x01));//等待时钟稳定
USBCLK = 0x00; //使用CDC功能需要使用这两行,HID功能禁用这两行。
USBCON = 0x90;
}
void delay_ms(u16 ms) //unsigned int
{
u16 i;
do
{
i = MAIN_Fosc/6000;
while(--i);
}while(--ms);
}