b2c的電子商務(wù)的網(wǎng)站建設(shè)焊工培訓(xùn)內(nèi)容
目錄
SPI+數(shù)碼管
SPI通信
SPI總線介紹
字節(jié)交換原理
時序單元
???????SPI模式
模式0
模式1
模式2
模式3
數(shù)碼管
介紹
74HC595芯片分析
???????原理圖分析
???????cubeMX配置???????
程序編寫
硬件SPI
???????軟件SPI
作業(yè):
SPI+數(shù)碼管
SPI通信
SPI總線介紹
SPI接口是Motorola 首先提出的全雙工三線/四線同步串行外圍接口采用主從模式(Master Slave)架構(gòu)。
時鐘由Master控制,在時鐘移位脈沖下,數(shù)據(jù)按位傳輸,高位在前,低位在后(MSB first);SPI接口有2根單向數(shù)據(jù)線,為全雙工通信。
SPI總線被廣泛地使用在FLASH、ADC、LCD等設(shè)備與MCU間,要求通訊速率較高的場合。
一主多從的同步串行全雙工通信
Master 主機(jī) Slave 從機(jī)
MISO 主機(jī)輸入從機(jī)輸出 MOSI 主機(jī)輸出從機(jī)輸入 SS Slave Select(片選線)從機(jī)選擇
SCK system clock 時鐘
所有的輸出口在輸出的時候要配置成推挽輸出,這樣在沒有外部上拉電阻的情況的也可以有較強(qiáng)的輸出高低電平的能力。但需要考慮一點(diǎn):當(dāng)主機(jī)跟從機(jī)3進(jìn)行通信的時候,從機(jī)2和從機(jī)1的MISO線如果是推挽輸出(推挽必輸出高電平或低電平的一種)那肯定會影響主機(jī)跟從機(jī)三的正常通信,所以為了消去這一影響,讓從機(jī)SS片選線為高電平,即非選中狀態(tài)時對應(yīng)從機(jī)輸出口置為高阻態(tài),這樣既不是高電平也不是低電平不會影響主機(jī)跟所選中從機(jī)的正常通信。
字節(jié)交換原理
字節(jié)交換基于位交換的
位交換分為兩部分:移出 移入
移出:就是把當(dāng)前移位寄存器的最高位寫到信號線上,然后整體往左移動一位
移入(采樣):讀取信號線的狀態(tài),然后把讀到的狀態(tài)放到寄存器的最低位
移入 主機(jī)和從機(jī)同時進(jìn)行
移出 主機(jī)和從機(jī)同時進(jìn)行
移入和移出的時機(jī)是由時鐘線控制約定的,約定好第幾個邊沿一起移出,第幾個邊沿一起移入。
???????時序單元
?起始條件:SS從高電平切換到低電平
?終止條件:SS從低電平切換到高電平
???????SPI模式
由CPOL及CPHA的不同狀態(tài),SPI分成了四種模式,主機(jī)與從機(jī)需要工作在相同的模式下才可以正常通訊,因此通常主機(jī)要按照從機(jī)支持的模式去設(shè)置
CPOL: 時鐘極性
CPHA: 時鐘相位
模式0
模式1
模式2
模式3
數(shù)碼管
介紹
LED數(shù)碼管(LED Segment Displays)是由8個發(fā)光二極管構(gòu)成,并按照一定的圖形及排列封裝在一起的顯示器件。其中7個LED構(gòu)成7筆字形,1個LED構(gòu)成小數(shù)點(diǎn)(固有時成為八段數(shù)碼管)。
LED數(shù)碼管有兩大類,一類是共陰極接法,另一類是共陽極接法,共陰極就是7段的顯示字碼共用一個電源的負(fù)極,是高電平點(diǎn)亮,共陽極就是7段的顯示字碼共用一個電源的正極,是低電平點(diǎn)亮。
我們對數(shù)碼管所要顯示的每個數(shù)字和字母進(jìn)行編碼,然后在編程時,將編碼放在一個數(shù)組上,需要顯示什么數(shù)字或者字母,從數(shù)組里面提取相應(yīng)的編碼就可顯示所要顯示的字符了。
如圖,要顯示數(shù)字“5”時,編碼為0x6D。如果數(shù)碼管為共陽極,只需要對共陰極的編碼做一個取反操作即可。
74HC595芯片分析
一定好好看此文章
一文搞懂74HC595芯片(附使用方法)_74hc595芯片引腳圖及功能-CSDN博客
???????原理圖分析
我們本次所使用的是一款四段共陰極八位數(shù)碼管,每個數(shù)碼管的使能相對獨(dú)立,各個數(shù)碼管使用對應(yīng)的三極管(NPN)進(jìn)行使能控制。
由于數(shù)碼管所需的管腳較多,我們使用SPI總線+74HC595(背過)芯片實現(xiàn)對數(shù)碼管的控制。
(注:圖中SPI4對應(yīng)的即為SPI2)
74HC595是一款8位串行輸入、并行輸出的位移寄存器,在本次項目中,使用其將SPI串行傳遞過來的數(shù)據(jù)并行發(fā)送給對應(yīng)數(shù)碼管與顯示位。SER為數(shù)據(jù)輸入引腳。
位信號為:
SPI2_NSS——PB12(鎖存,可設(shè)置為Output,低-》高就可以命令595芯片并行輸出)
SPI2_SCK——PB13(SPI時鐘)
SPI2_MISO——PB14(主機(jī)輸入從機(jī)輸出)---對本例子不重要
SPI2_MOSI——PB15(主機(jī)輸出從機(jī)輸入)
???????cubeMX配置
程序編寫
硬件SPI
/* USER CODE BEGIN 0 */
//定義一個保存了所有數(shù)字顯示狀態(tài)的數(shù)組
const uint8_t number[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //數(shù)字顯示//定義一個用于保存想要顯示的數(shù)字的變量
volatile uint16_t show_number = 0x1234; //使用volatile使變量不被優(yōu)化,每次都刷新讀取//數(shù)碼管顯示函數(shù)
void led_dispaly()
{
uint8_t which_where_data[2] = {0x00, 0x00}; //創(chuàng)建一個用于保存段選與位選的數(shù)組//使用switch進(jìn)行判斷,由于一次只能點(diǎn)亮一個,需要引入一個變量進(jìn)行自增,循環(huán)對應(yīng)各數(shù)碼管static uint8_t choose = 0; //用于位循環(huán)switch(choose){case 0:
which_where_data[0] = 0x08; //1-4位順序為 0x01 0x02 0x04 0x08
which_where_data[1] = number[show_number & 0x000F]; //將想要顯示的數(shù)字與之相&,就相當(dāng)于蓋上了其他位//SPI傳輸函數(shù),參數(shù)為使用的SPI通道、要傳輸?shù)臄?shù)據(jù)、數(shù)據(jù)長度、超時時間HAL_SPI_Transmit(&hspi2,which_where_data,2,10);//進(jìn)行鎖存操作,等效于寫入一高一低電平HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);HAL_Delay(1);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET); choose++; //移動至下一位break;case 1:
which_where_data[0] = 0x04; //1-4位順序為 0x01 0x02 0x04 0x08
which_where_data[1] = number[show_number>>4 & 0x000F]; // >>4 取第三位//SPI傳輸函數(shù),參數(shù)為使用的SPI通道、要傳輸?shù)臄?shù)據(jù)、數(shù)據(jù)長度、超時時間HAL_SPI_Transmit(&hspi2,which_where_data,2,10);//進(jìn)行鎖存操作,等效于寫入一高一低電平HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);HAL_Delay(1);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);
choose++; //移動至下一位break;case 2:
which_where_data[0] = 0x02; //1-4位順序為 0x01 0x02 0x04 0x08
which_where_data[1] = number[show_number>>8 & 0x000F];//SPI傳輸函數(shù),參數(shù)為使用的SPI通道、要傳輸?shù)臄?shù)據(jù)、數(shù)據(jù)長度、超時時間HAL_SPI_Transmit(&hspi2,which_where_data,2,10); //進(jìn)行鎖存操作,等效于寫入一高一低電平HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);HAL_Delay(1);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET); choose++; //移動至下一位break;case 3:
which_where_data[0] = 0x01;//1-4位順序為 0x01 0x02 0x04 0x08
which_where_data[1] = number[show_number>>12 & 0x000F]; //SPI傳輸函數(shù),參數(shù)為使用的SPI通道、要傳輸?shù)臄?shù)據(jù)、數(shù)據(jù)長度、超時時間HAL_SPI_Transmit(&hspi2,which_where_data,2,10); //進(jìn)行鎖存操作,等效于寫入一高一低電平HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);HAL_Delay(1);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);
choose = 0; //移動循環(huán)break;}
}
/* USER CODE END 0 */
???????軟件SPI
1.先配置引腳為輸出模式
2.右鍵改名字
改成如下
/* USER CODE BEGIN 0 */
void led_dispaly (uint8_t Bit,uint8_t Seg)//0x01 0x66 第一個管寫4
{
int i=0;
for(i=0;i<8;i++)
{
HAL_GPIO_WritePin(GPIOB,SPI2_SCK_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, SPI2_MOSI_Pin, (Bit & 0x80) ? 1 : 0);
HAL_GPIO_WritePin(GPIOB,SPI2_SCK_Pin,GPIO_PIN_SET);Bit<<=1;
HAL_Delay(1);
}
for(i=0;i<8;i++)
{
HAL_GPIO_WritePin(GPIOB,SPI2_SCK_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, SPI2_MOSI_Pin, (Seg & 0x80) ? 1 : 0);
HAL_GPIO_WritePin(GPIOB,SPI2_SCK_Pin,GPIO_PIN_SET);
Seg<<=1;
HAL_Delay(1);
}
HAL_GPIO_WritePin(GPIOB, SPI2_NSS_Pin, 0);
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOB, SPI2_NSS_Pin, 1);
}/* USER CODE END 0 */
作業(yè):
通過串口發(fā)送相應(yīng)的數(shù)字來控制數(shù)碼管的輸出,個位數(shù)
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include<stdlib.h>
#include<string.h>
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void SystemPower_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//**
* @brief The application entry point.
* @retval int
*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* Configure the System Power */SystemPower_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_SPI2_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */char buf[5]={0};uint8_t i=0;const uint8_t number[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //數(shù)字顯示uint8_t shi=0;uint8_t gewei=0; uint8_t send[2]={0};/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */HAL_UART_Receive(&huart1,buf,5,8);//每次運(yùn)行到此處,等3ms看看有沒有數(shù)據(jù)發(fā)送過來
i=atoi(buf);//取出i的十位和個位
shi=i/10;
gewei=i%10;//將十位顯示在1號管0x01
send[0]=0x01; // 0001
send[1]=number[shi];HAL_SPI_Transmit(&hspi2,send,2,100);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,0);HAL_Delay(1);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,1);//將個位顯示在2號管0x02
send[0]=0x02;
send[1]=number[gewei];HAL_SPI_Transmit(&hspi2,send,2,100);//向74HC595串行輸出HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,0);//產(chǎn)生上升沿,并行輸出HAL_Delay(1);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,1);}/* USER CODE END 3 */
}/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Configure the main internal regulator output voltage
*/if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE4) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_4;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2|RCC_CLOCKTYPE_PCLK3;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK){Error_Handler();}
}/**
* @brief Power Configuration
* @retval None
*/
static void SystemPower_Config(void)
{/*
* Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral
*/HAL_PWREx_DisableUCPDDeadBattery();
/* USER CODE BEGIN PWR */
/* USER CODE END PWR */
}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
key1來控制數(shù)碼管的數(shù)字顯示,按一下+1,大于15歸零
/* USER CODE BEGIN 2 */uint8_t i=0;const uint8_t number[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //數(shù)字顯示uint8_t shi=0;uint8_t gewei=0; uint8_t send[2]={0};/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_9)==0){while(!HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_9));
i++;if(i>15){
i=0;}}//取出i的十位和個位
shi=i/10;
gewei=i%10;//將十位顯示在1號管0x01
send[0]=0x01; // 0001
send[1]=number[shi];HAL_SPI_Transmit(&hspi2,send,2,100);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,0);HAL_Delay(1);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,1);//將個位顯示在2號管0x02
send[0]=0x02;
send[1]=number[gewei];HAL_SPI_Transmit(&hspi2,send,2,100);//向74HC595串行輸出HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,0);//產(chǎn)生上升沿,并行輸出HAL_Delay(1);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,1);}