|
本帖最后由 bwwjsbzd 于 2023-7-17 20:36 编辑
大一就在学STC8A8k64D4的开发。
第一课:认识单片机
这节课内容相对简单。
1.介绍了一下单片机的定义
2.简单介绍了stc的功能和用途。
功能:读取电压,输出电平,计时,计数,等。
用途:基本啥都能干,功能很多。
总的来说挺简单的。
第二课:认识硬件
这节课介绍了开发板上的硬件外设。
比STC8a8k64d4外设丰富很多,功能也多上不少。
也看到了很多从来没有接触到的外设。
第三课:开发环境搭建和程序下载这是学习嵌入式单片机的基础,也是非常简单的。
还是在复习一下
接下来就来介绍一下。
1.stc-isp下载
https://stcai.com/gjrj 网址下载。
2.手册下载
stc-isp工具顶部菜单 资料下载 - 手册下载 - 找到stc32系列。
也可以在官网下载。
3.4.pdf阅读器
这个没啥说的,我自己用的苏门答腊pdf 。
记得擅用书签,搜索等功能。
5.c251环境搭建
根据手册上的链接下载c351xxx.exe,一路next就行。
6.程序包下载
stc-isp顶部菜单 资料下载-软件库函数-stc32G库函数
7.编译
stc-isp中添加型号和头文件到keil中
打开下载好的stc32g库函数中的工程文件(.uvproj),这里以跑马灯为例。
点击keil左上的编译 链接 按钮 完成编译,如果编译成功,下方会出现0 errors。
8.下载
装好驱动。
选好芯片和端口
通过usb接口下载。
按住p3^2按钮,再按电源按钮,最后再松开p3^2按钮。
点击下载,完成下载。
这样。hex文件就被烧录进单片机可以看看实际运行结果了。
第四课 :建立工程点亮第一颗LED
1.点亮led原理
GPIO 可以通过软件读取其输入电平或控制他输出高低电平。
GPIO----发光二极管 -----限流电阻 ----- 5v (注意二极管方向)
此时GPIO 输出低电平,发光二级管就会被点亮。
类似的还有发光二极管负端接地,GPIO 输出高电平。
2.新建Keil项目
打开keil
点击顶部菜单project- new uvision project,在弹出的对话框输入你的工程名字 0.1DEMO
选择STC MCU 数据库,选择stc32g 单片机
点击file-new 新建 文件
点击file-save 保存文件 文件名 Demo.c
3.写代码 点灯仪式
sfr P0 = 0x80;
sfr P1 = 0x90;
sbit LED1 = P0 ^ 7; /*!< LED1 引脚定义 */
sbit LED2 = P0 ^ 6;
sbit LED4 = P0 ^ 4; /*!< LED1 引脚定义 */
/*!< LED1 引脚定义 */
/*
传统的 8051 单片机上电后即为准双向口模式并输出高电平,
STC8A8K64D4系列单片机的 I/O 上电后为高阻输入模式。在向
外输出信号前,要先使用 PxM0 和 PxM1 两个寄存器对 I/O
的工作模式进行设置。
*/
sfr P0M0 = 0x94; //0000,0000 端口0模式寄存器0
sfr P0M1 = 0x93; //0000,0000 端口0模式寄存器1
sfr P1M0 = 0x92;
sfr P1M1 = 0x91;
int main()
{
P0M0 = 0;
P0M1 = 0;
P1M0 = 0;
P1M1 = 0;
while(1)
{
LED1 = 0;
LED2 = 0;
LED4 = 0;
}
}
第五课 C语言运算符和进制数入门
C语言的运算符和进制都是学习嵌入式的基础。
打印函数中可以添加格式字符,常见的格式字符有%d 整形 %f 浮点 %lf 双浮点 %o 8进制 %x 16进制 %c字符 %s字符串也可添加标志 n.m - 空格 #
常见的转义字符 \r\n windows中的换行符 。
例 printf("温度:%.2f \r\n",15,8);
stc-isp中得到的输出就是 《温度:15.80》。
打印函数在单片机中实际上是以ascii码进行传输的,课程中也给出了ascii码表,在stc-isp中可以查看接收到的ascii (hex)数据。
算数运算符:主要是加减乘除 ,取余,自增自减就是基本的常用的数学运算。
位运算符:移位 按位与/或 取反
放到二进制中就很好理解了,左移,右移,就是将每一位进行移动,空的补0.
例:1101 0011 << 2 = 11 0100 1100;
按位与/或 就是将对应的位相与/或;
例:1000 0001 & 1000 0000 = 1000 0000;
1000 0001 & 1000 0000 = 1000 0001;
取反就是将所有位取反;
!1000 0000 = 0111 1111;
第六课 LED闪烁和花式点灯
1s=1000ms = 1000 000 us
定义时钟频率为24M define 是c的宏定义
#define MAIN_Fosc 24000000UL
STC-ISP也有延时函数的生成。
列如:
void Delay1ms() //@24.000MHz
{
unsigned long edata i;
_nop_();
_nop_();
_nop_();
i = 5998UL;
while (i) i--;
}
在主函数循环中调用延时函数
点灯 延时 关灯 延时
P40 = 0;
Delay1ms();
P40 = 1;
这个delay 使用方便 但弊端是占用单片机的内存。单片机不能做别的事情。
3.新建文件使用模块化编程
新建xxx.c 和xxx.h
xxx.h中:
#ifndef __XXX_H_
#define __XXX_H_
调用头文件
函数声明
#endif
xxx.c中:
#include “xxx.h”
函数定义
例:
math.h
#ifndef __MATH_H_
#define __MATH_H_
int add(int int);
#endif
math.c
#include "math.h"
int add (int parm1, int parm2)
{
return parm1+parm2;
}
第七课 按键点灯
1.按键的原理
常见用法:
sys-vcc
|
io - 电阻 - - 按键 - gnd
按键有抖动5-10ms
2.按键的代码
if(key == 0)
{
delay_ms(10);
if(key == 0)
{
P60 = !P60; //点灯取反
while(key == 0);
}
}
按键按下执行的动作
可以使用<< 移位来实现
3.按键的应用
点击点灯,松开灭灯;
点击灭灯,松开点灯; 这两个直接赋值就行
按下一次, 改变一次; 这个取反
按下一次,左走一个; 这个移位
4.数组
定义 类型[长度] = {值}
使用 名称[索引] = 值;
例: int a[2] = {0, 1, 2}
a[1] = 8;
第八课 蜂鸣器的应用
1.认识蜂鸣器
分有源和无源的,有缘的略贵,因为有震荡源,有黑胶,通电就叫。
P54 高关闭 P54 低开启
自己的尝试:
#define buzzer P54
if(key == 0)
{
delay_ms(10);
if(key == 0)
{
buzzer = !buzzer //点击按键蜂鸣器开,再点关。
while(key == 0);
}
}
作业 :
#define key3 P36
u8 working = 0;
if(key3 == 0)
{
delay_ms(10);
if(key3 == 0)
{
working = !working;
while(key3 == 0);
}
}
if(working)
{
led = 0;
delay_ms(200);
led = 1;
delay_ms(200);
}
第九课 数码管的静态使用
1.认识数码管
开发板上有2个4位数码管
长啥样的都有,内部有led
本质还是点灯,和点亮led相同
8字的里面有8个灯abcdefg dp,分共阳极 和共阴极
共阳的给低电平 共阴的给高电平
4位的abcdefg dp 是连在一起的
2.控制原理 共阳极
C0 F9 A4 B0 99 92 82 F8 80 90
对应 0 1 2 3 4 5 6 7 8 9
3.数码管实现0-9的显示
先定义个数组SEG_Tab[10],把10个数字对应的16进制值存储进去
P70 = 0; //P70 对应最后那个数码管
P6 = SEG_Tab[0] //显示0
按按键便利数组SEG_Tab并给P6赋值,可以得到0-9 的显示
if(key2 == 0)
{
delay_ms(10);
if(key2 == 0)
{
if(num<9)
{
num++;
}
while(key2 == 0);
}
}
if(key == 0)
{
delay_ms(10);
if(key == 0)
{
if(num<9)
{
num--;
}
while(key == 0);
}
}
P6 = SEG_Tab[num] //显示
也可以加上蜂鸣器 ,每次按按键就会滴滴响,并切换数码数值。
第十课 数码管的动态显示
1.数码管动态刷新原理
依次打开每个位的公共阳极端,关闭其他的,
同时 输入对应位的段码,就行了。
2. 8位数码管点亮
增加位码 数组 COM_Tab
增加显示 数组 Show_Tab
定义 int num 变量
P7 = COM_Tab[num];
P6 = SEG_Tab[Show_Tab[num]];
delay_ms(1);
num++;
if(num >7)
num = 0;
即可实现8位数码管点亮。
第十一课 定时器的使用
1.定时器的意义和作用
while循环中的每隔1ms加1 受while影响
定时器 每隔固定时间完成操作可以脉冲计数 或替代delay
2.定时器应用
手册上有个很清晰的定时器0 16位计数器的流程图
TMOD = 0x00; //模式 0
TL0 = 0x30; //24M 1ms
TH0 = 0xF8;
TR0 = 1; //启动定时器
ET0 = 1; //使能定时器中断
EA = 1;
void tim0_isr() interupt 1
{
//在这写中断函数的代码
}
stc-isp 定时器计算器很好用
课后练习:
void Timer0Init(void) //10毫秒@24.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xE0; //设置定时初始值
TH0 = 0xB1; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void tim0_isr() interupt 1
{
if(num>100)
{
clock++; //时间变量(s)
num = 0;
}
}
sec = clock % 7200;
min = clock /60 %60;
hour = clock /7200;
第十二课 计数器
1.计数器的用途
马达 编码器
2.计数器配置
T1_C/T 置1为计数器
T0_GATE 控制开关
TH1 TL1 计数用的
3.计数器应用
TMOD = 0x40; //计数模式
TL1 = 0xff;
TH1 = 0xff;
TF1 = 1;
TR1 = 1;
ET0 = 1;
EA = 1;
void Timer0_Isr(void) interrupt 3
{
P60 = !P60;
}
M法测速
n=M0/CT0
还是没太学清楚。
第十三课 简易多任务处理
1.回顾
GPIO 应用 和 TIM
重点清理程序的逻辑电路
2.模块化编程 .c .h
LED&数码管 led_seg.c (.h)
按键 key.c(.h)
蜂鸣器 beep.c(.h)
定时器 tim.c(.h)
函数添加注释
添加软件头
.h 中添加引脚定义
sbit name = P10;
#define name P10
函数
定义
声明
调用
extern
a.c 中 引用 b.c 的变量要加
bdata
可以寻址每个位
u8 bdata LED = 0x00;
sbit LED0 = LED^0;
sbit LED1 = LED^1;
3.工程文件编写
这里将之前的代码都整理了一遍
拆分成了4个模块,
在key模块中引入了状态机的概念,
实现了短按,长按等功能,
记住一个模块一个.c.h
声明放到.h 中
第十四课 矩阵键盘
先0-3 输出第电平 6-7 输出高电平
如果有按键按下,那一列io就变低电平 判断哪一列
后0-3 输出高电平 6-7输出低电平
按下那一行的io就会变成低电平,判断出哪一列
矩阵按键程序的编写
u8 MaterixKey_Read()
{
u8 keystate; //状态
u8 key_val = 0;
MaterixKey = 0xC0;
delay_ms(10);
keystate = MateixKey ^ 0xC0;
MaterixKey = 0x0f;
delay_ms(10);
keystate |= (MateixKey ^ 0x0f);
printf("0x%02x \r\n",keystate);
switch(keystate)
{
case 0x41: key_val = 1;
break;
case 0x42: key_val = 2;
break;
case 0x44: key_val = 3;
break;
case 0x48: key_val = 4;
break;
case 0x81: key_val = 5;
break;
case 0x82: key_val = 6;
break;
case 0x84: key_val = 7;
break;
case 0x88: key_val = 8;
break;
default: key_val = 0;
break;
}
KEY_NUM = MaterixKey_Read();
SEG7 = KEY_NUM;
return keystate;
}
第十五课 外部中断
1.中断和中断系统
cpu暂停,处理紧急事件,处理完继续原来的工作
相应优先级高的中断
中断可以独立开关
部分优先级可以设置
2.什么是外部中断
外部电平变化产生的中断
写着INT的引脚是外部中断口
3.外部中断的用法
外部中断0
IT0
IE0
EX0
EA
外部中断1
IT1
IE1
EX1
EA
外部中断x
INTxIF
EXn
EA
4.外部中断用法
IT0 = 1; //使能 INT0 上升沿和下降沿中断
EX0 = 1; //使能 INT0 中断
IE = 0;
EA = 1;
void INT0_Init() interrupt 0
{
LED0 = !LED0;
}
总结:
学到了很多,也对一些东西进行了改写。
/* 函数体 -----------------------------------------------------------*/
/*
* 功能: GPIO 端口初始化
* 参数: gpio: GPIO端口, GPIO_P0 - GPIO_P7
* pin: I/O引脚, GPIO_Pin_0 - GPIO_Pin_7 IO引脚 Px.0-7
* GPIO_Pin_LNIB IO引脚低 4 位
* GPIO_Pin_HNIB IO引脚高 4 位
* GPIO_Pin_All IO所有引脚
* mode: 工作模式
* 返回:SUCCESS 返回成功。
* ERROR 返回失败。
*/
//#define chr(x) #@x
//ErrorStatus GPIO_Initl(uint8_t gpio_x, uint8_t pin, eGPIO_Mode mode)
//{
// if(gpio_x > GPIO_P7) return ERROR;
//
// if(mode & BIT0) Px_M0(gpio_x) |= (pin);
// else Px_M0(gpio_x) &= ~(pin);
//
// if(mode & BIT1) Px_M1(gpio_x) |= (pin);
// else Px_M1(gpio_x) &= ~(pin);
// return SUCCESS;
//}
typedef enum
{ /* IO 模式 */
GPIO_MODE_WEAK_PULL = 0x00, /*< 上拉准双向口 */
GPIO_MODE_OUT_PP = 0x01, /*< 推挽输出 */
GPIO_MODE_IN_FLOATING = 0x02, /*< 浮空输入 */
GPIO_MODE_OUT_OD = 0x03, /*< 开漏输出 */
/* IO 控制 */
GPIO_CTRL_PULLUP = 0x10, /*< 上拉电阻 */
GPIO_CTRL_ST = 0x20, /*< 施密特触发器 */
GPIO_CTRL_SPEED = 0x40, /*< 电平翻转速度 */
GPIO_CTRL_DRIVE = 0x80, /*< 驱动电流 */
} eGPIO_Mode;
/* GPIO Bit SET和Bit RESET枚举 */
typedef enum
{
GPIO_PIN_RESET = 0,
GPIO_PIN_SET = 1
} eGPIO_PinState;
|
|