【STM8】使用SPI通讯控制多个级联MBI5043 一一代码实现

整体架构

摘要:
本章内容包含了时钟初始化,引脚初始化,逻辑函数的实现。逻辑函数的重点内容是 资料锁存函数中的注意事项,映射函数的含义。全部项目代码在文章末尾

#include "STM8S103F.h"
#include "port_def.h"
#include "string.h"	
#define n_MBI5043_1_stm8 3	
typedef unsigned char u8;
typedef unsigned short int u16;
main()
{
   
	u16 dis_buf[48] = {
   
0x00,0,0,//LED1 LR1,LG1,LB1
0x00ff,0,0,
0x00ff,0,0,
0x00ff,0,0,//led4

0x00ff,0,0,
0x00ff,0,0,
0x00ff,0,0,
0x00ff,0,0,

0,0,0,
0,0,0,
0,0,0,
0,0,0,

0,0,0,
0,0,0,
0,0,0,
0,0,0}; //led16 LR16,LG16,LB16
	oclk_init();   //时钟初始化肯定得有
	port_init();	//引脚初始化肯定得有
	spi_init();		//用到了SPI,所以也要初始化
	TIM4_init();	//有用到TIM4定时器做延时,所以也要初始化
	star_falling(dis_buf);	//然后就是逻辑实现函数了
}

把要完成的工作拆分成几个小项


初始化三部曲—时钟,引脚,外设

  • 从“时钟初始化”先开始
    先上代码
void oclk_init(void)
{
   
	CLK_CKDIVR=0x00;	//f_cpu = f_HIS RC输出=16Mhz
	
	CLK_PCKENR1 |=0X12;  //使能f_MASTER与外设(tim4和spi)的连接
	
	while(CLK_CCOR&0x40);	//可配置时钟输出不忙,next
	CLK_CCOR=0x0d;			//设置f_clk_coo = f_cpu/4 = 4Mhz
}

走到这一步就可以翻开STM8S的参考手册了,8.1-8.8小节是对时钟详细介绍和控制逻辑;读写 8.9小节的时钟寄存器来实现对时钟的控制。*
名词解释

f_MASTER(内部时钟) = f_HIS RC输出/(2^HSI分频因子)
f_cpu (CPU时钟) = f_MASTER/(2^CPU时钟预分频因子)

首先,我们要确定上电后默认时钟对吧,再就是确定CPU时钟对吧。

时钟分频寄存器(CLK_CKDIVR)

其次,就是外设,像spi,uart,ADC,TIMx’····,也需要连接时钟

外设时钟门控寄存器(CLK_PCKENR1) 

最后,外部管脚CCO也需要输出指定的时钟。翻看上一章方案制定的原理图图2,GCLK连接的引脚是PC4/CLK_COO。

可配置时钟输出寄存器(CLK_CCOR)
  • 第二想到的非管脚配置莫属
    接着先上代码
#ifndef _port_def_
	#define _port_def_										

	#define LA	                        3
	#define OutLA	    	            PC_DDR |=  (1<<LA)
	#define OUTELA                      PC_CR1 |=  (1<<LA)
	#define OpenLA                      PC_ODR |=  (1<<LA)
	#define CloseLA                     PC_ODR &= (~(1<<LA))
		
	#define DCLK	                    5
	#define OutDCLK	                    PC_DDR |=  (1<<DCLK)
	#define OUTEDCLK                    PC_CR1 |=  (1<<DCLK)
	#define OpenDCLK                    PC_ODR |=  (1<<DCLK)
	#define CloseDCLK 	                PC_ODR &= (~(1<<DCLK))
		
	#define DISPDATA	                6
	#define OutDISPDATA	                PC_DDR |=  (1<<DISPDATA)
	#define OUTEDISPDATA                PC_CR1 |=  (1<<DISPDATA)
	#define OpenDISPDATA                PC_ODR |=  (1<<DISPDATA)
	#define CloseDISPDATA	            PC_ODR &= (~(1<<DISPDATA))		
	

	#define GCLK                     	4
	#define OutGCLK	                    PC_DDR |=  (1<<GCLK)
	#define OUTEGCLK                    PC_CR1 |=  (1<<GCLK)
	#define OUTE2GCLK                   PC_CR2 |=  (1<<GCLK)		
	#define OpenGCLK                    PC_ODR |=  (1<<GCLK)
	#define CloseGCLK 	                PC_ODR &= (~(1<<GCLK))
#endif

#include "port_def.h"
void port_init(void)
{
   	
	OutLA;			//选择引脚 输出模式
	OUTELA;			//输出模式时 推挽输出
	CloseLA;
		
	OutDCLK;
	OUTEDCLK;
	CloseDCLK;

	OutDISPDATA;
	OUTEDISPDATA;
	CloseDISPDATA;	
	
	OutGCLK;
	OUTEGCLK; 
	OUTE2GCLK; 		  //在输出模式下,置位将提高IO速度
}

同样,翻开STM8S的参考手册了,11节就是对通用输入输出口(GPIO) 的描述,同样是通过寄存器读写来实现对GPIO的操作。看手册还是不理解,看别人写的幼儿园化 引脚 - 初始化介绍

下面几个事项要特别留意

  1. 初始化的时候信号最后都置无效。GCLK接的是时钟,不需要额外干涉

    CloseLA;CloseDCLK;CloseDISPDATA;

  2. 特别对GCLK的PC_CR2寄存器进行照顾。也是因为GCLK接的是时钟

    OUTE2GCLK; //在输出模式下,置位将提高IO速度

  • SPI初始化

  • 第三章介绍单线(MOSI一根线)单向(master out),只发送不接收情况下SPI初始化和发送配置问题。

  • TIM4初始化

  • 第三章介绍TIM4用作精准延时情况下,TIM4初始化和发送配置问题。


逻辑实现函数(star_falling(dis_buf))

代码如下:

#include "string.h"	  //memcpy函数属于string.h库
void star_falling(u16 dis_buf[])
{
   
	u16 temp[48];
	u8 i;
	/* while(1)
	{
		for(i=0;i<45;i++)
		{
			temp[i] = dis_buf[i+3];
		}
		for(i=45;i<48;i++)
		{
			temp[i] = dis_buf[i-45];
		}
		for(i=0;i<48;i++)
		{
			dis_buf[i] = temp[i];
		}
		
		display(dis_buf);
		delay(10);
	} */
	while(1)
	{
   
		memcpy(temp,dis_buf+3,15*3*2);
		memcpy(temp+45,dis_buf,3*2)
由于实现双网口级联需要涉及到硬件的配置和多线程处理,这里只提供一个基本框架供参考: ``` #include "stm32f4xx_hal.h" #include "stm32f4xx_hal_eth.h" // 定义以太网MAC控制器的句柄和配置结构体 ETH_HandleTypeDef heth1; ETH_HandleTypeDef heth2; ETH_InitTypeDef eth1_config; ETH_InitTypeDef eth2_config; // 定义接收和发送缓冲区 uint8_t eth1_rx_buffer[ETH_RX_BUFFER_SIZE]; uint8_t eth1_tx_buffer[ETH_TX_BUFFER_SIZE]; uint8_t eth2_rx_buffer[ETH_RX_BUFFER_SIZE]; uint8_t eth2_tx_buffer[ETH_TX_BUFFER_SIZE]; // 定义以太网MAC控制器的中断处理程序 void ETH1_IRQHandler(void) { // 处理接收缓冲区中的数据,并将数据复制到eth2_tx_buffer中 } void ETH2_IRQHandler(void) { // 处理接收缓冲区中的数据,并将数据复制到eth1_tx_buffer中 } int main(void) { // 初始化硬件和配置以太网MAC控制器 HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ETH_Init(&heth1, &eth1_config, &eth1_rx_buffer, &eth1_tx_buffer); MX_ETH_Init(&heth2, &eth2_config, &eth2_rx_buffer, &eth2_tx_buffer); // 启动以太网MAC控制器 HAL_ETH_Start(&heth1); HAL_ETH_Start(&heth2); while (1) { // 检查eth1_rx_buffer中是否有数据,如果有则将数据复制到eth2_tx_buffer中 // 检查eth2_rx_buffer中是否有数据,如果有则将数据复制到eth1_tx_buffer中 } } ``` 需要注意的是,以上代码只是一个基本框架,需要根据具体情况进行调整和优化。例如,可以在中断处理程序中使用DMA来传输数据,或者使用操作系统的多线程机制来处理数据。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值